Esempio n. 1
0
    def _create_terminal(self):
        assert self._terminal is None, \
            "should only call _create_terminal once"

        self._terminal_button = QToolButton(None)
        self._terminal_button.setToolTip("Toggle command line")
        self._ui.layerWidget.button_row.addWidget(self._terminal_button)
        self._terminal_button.setArrowType(Qt.DownArrow)

        try:
            from .widgets.terminal import glue_terminal
            widget = glue_terminal(data_collection=self._data,
                                   dc=self._data,
                                   hub=self._hub,
                                   **vars(env))
            self._terminal_button.clicked.connect(self._toggle_terminal)
        except Exception as e:  # pylint: disable=W0703
            import traceback
            self._terminal_exception = traceback.format_exc()
            self._setup_terminal_error_dialog(e)
            return

        splitter = QSplitter(self)
        splitter.setOrientation(Qt.Vertical)
        splitter.addWidget(self._ui.centralwidget)
        splitter.addWidget(widget)
        splitter.setStretchFactor(0, 5)
        splitter.setStretchFactor(1, 1)

        self.setCentralWidget(splitter)
        self._terminal = widget

        self._hide_terminal()
 def _initMainWidget(self):
     split = QSplitter(Qt.Horizontal, self)
     split.addWidget(self._peerList)
     split.addWidget(self._historyTable)
     split.setStretchFactor(0, 0)
     split.setStretchFactor(1, 1)
     return split
Esempio n. 3
0
    def __setup_ui(self):
        self.resize(1024, 768)
        self.__setup_menu()

        split = QSplitter()
        self.__mib_tree_widget = MibTreeWidget()
        split.addWidget(self.__mib_tree_widget)
        #
        self.__data_widget = DataWidget()
        split.addWidget(self.__data_widget)
        split.setHandleWidth(2)
        split.setStretchFactor(0, 1)
        split.setStretchFactor(1, 200)

        la = QVBoxLayout()
        self.__progress_bar = QProgressBar()
        self.__progress_bar.setValue(0)
        self.__progress_bar.setVisible(False)
        la.addWidget(self.__progress_bar, 1)
        la.addWidget(split, 1)

        cw = QWidget()
        cw.setLayout(la)

        self.setCentralWidget(cw)
Esempio n. 4
0
    def _create_central_widget(self):

        tabs = QTabWidget()

        splitter = QSplitter()
        self.treeview = QTreeView()
        self.treeview.header().hide()
        self.treeview.resize(500, 0)
        splitter.addWidget(self.treeview)

        self.editwidget = QWidget()
        self.editwidget.setLayout(QVBoxLayout())
        self.editwidget.resize(300, 300)
        self.editwidget.setMinimumSize(300, 100)
        splitter.addWidget(self.editwidget)

        self.glwidget = GLWidget()
        splitter.addWidget(self.glwidget)

        splitter.setStretchFactor(0, 2)
        splitter.setStretchFactor(1, 2)
        splitter.setStretchFactor(2, 4)

        tabs.addTab(splitter, "Mesh")

        tabs.addTab(self._create_run(), "Run")

        self.setCentralWidget(tabs)
Esempio n. 5
0
class PostProcessConfigWidget(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.tree = PostProcessModulesTreeWidget()
        self.config = PostProcessModulesConfig()
        self.connect(self.tree, SIGNAL("moduleClicked"), self.config.update)
        self.connect(self.tree, SIGNAL("moduleStateChanged"),
                     self.config.updateState)
        sizePolicy = QSizePolicy(QSizePolicy.Minimum,
                                 QSizePolicy.MinimumExpanding)
        sizePolicy.setVerticalStretch(1)
        self.setSizePolicy(sizePolicy)
        layout = QHBoxLayout()
        layout.setMargin(0)
        self.__splitter = QSplitter(Qt.Horizontal, self)
        layout.addWidget(self.__splitter)
        self.__splitter.addWidget(self.tree)
        self.__splitter.addWidget(self.config)
        self.__splitter.setStretchFactor(0, 0)
        self.__splitter.setStretchFactor(1, 80)
        self.setLayout(layout)

    def fillFromAnalyse(self):
        TaskManager().addAnalyseDependencies()
        self.tree.update()
Esempio n. 6
0
 def _initMainWidget(self):
     split = QSplitter(Qt.Horizontal, self)
     split.addWidget(self._actionList)
     split.addWidget(self._settingsWidget)
     split.setStretchFactor(0, 0)
     split.setStretchFactor(1, 1)
     return split
Esempio n. 7
0
    def createWidget(self):
        """
        Create the widget
        """
        self.diagramScene = QGraphicsScene(self)

        self.view = QGraphicsView(self.diagramScene)

        self.view.setRenderHint(QPainter.Antialiasing)

        # set the main layout
        layout = QVBoxLayout()

        self.logEdit = QTextEdit()
        self.logEdit.setReadOnly(True)

        hSplitter2 = QSplitter(self)
        hSplitter2.setOrientation(Qt.Vertical)

        hSplitter2.addWidget(self.view)
        hSplitter2.addWidget(self.logEdit)

        hSplitter2.setStretchFactor(0, 1)

        layout.addWidget(hSplitter2)
        self.setLayout(layout)
Esempio n. 8
0
class Help(QDockWidget):
    def __init__(self, parent=None, path=None):
        QDockWidget.__init__(self, parent)
        self.name = self.tr("Help")
        self.setFloating(False)
        self.setFeatures(QDockWidget.NoDockWidgetFeatures)

        self.__mainWidget = QSplitter(Qt.Horizontal)
        self.__uname = QWidget()

        mainWidgetLayout = QVBoxLayout(self.__uname)
        mainWidgetLayout.setContentsMargins(0, 0, 0, 0)

        # create helper + search engine
        self.__helper = QHelpEngine(path, self)

        if not self.__helper.setupData() is True:
            dialog = QMessageBox()
            
            msg = QString(self.tr("An error occurred while setting help engine up :\n"))
            msg += (self.__helper.error() + "\n")
            msg += self.tr("It might mean that the format of your help file is not correct.\n")
            msg += self.tr("You can check on-line help at http://wiki.digital-forensic.org")

            dialog.setText(msg)
            dialog.setIcon(QMessageBox.Warning)
            dialog.setWindowTitle(self.tr("Error while loading help"))
            dialog.exec_()
            return

        self.__toc = self.__helper.contentWidget()
        self.__helpBrowser = HelpBrowser(self.__helper)

        # build main widget
        self.__toolbar = QWidget()
        self.__toolbarLayout = QHBoxLayout(self.__toolbar)
        home = QPushButton(QIcon(":home.png"), "")
        previous = QPushButton(QIcon(":previous.png"), "")
        next = QPushButton(QIcon(":next.png"), "")

        # building toolbar
        self.__toolbarLayout.addWidget(home)
        self.__toolbarLayout.addWidget(previous)
        self.__toolbarLayout.addWidget(next)
        self.__toolbarLayout.setContentsMargins(0, 0, 0, 0)
        mainWidgetLayout.addWidget(self.__toolbar)
        mainWidgetLayout.addWidget(self.__helpBrowser)
        self.__mainWidget.insertWidget(0, self.__toc)
        self.__mainWidget.insertWidget(1, self.__uname)
        self.__mainWidget.setStretchFactor(1, 1)
        self.setWidget(self.__mainWidget)

        #connecting `previous`, `home` and `next` buttons
        self.connect(next, SIGNAL("clicked(bool)"), self.__helpBrowser.nextPage)
        self.connect(previous, SIGNAL("clicked(bool)"), self.__helpBrowser.prevPage)
        self.connect(home, SIGNAL("clicked(bool)"), self.__helpBrowser.goHome)
        self.connect(self.__helper.contentWidget(), SIGNAL("linkActivated(const QUrl &)"),
                     self.__helpBrowser.setSource)
 def setupViews(self):
     splitter = QSplitter()
     self.setupTaskTable()
     splitter.addWidget(self.taskTableWidget)
     self.taskViewWidget = taskviewwidget.TaskViewWidget()
     splitter.addWidget(self.taskViewWidget)
     splitter.setStretchFactor(0, 0)
     splitter.setStretchFactor(1, 1)
     self.setCentralWidget(splitter)
     self.taskViewWidget.hide()
     self.msgLabel = QLabel()
     self.statusBar().addWidget(self.msgLabel)
Esempio n. 10
0
 def setupViews(self):
     splitter = QSplitter()
     self.setupTaskTable()
     splitter.addWidget(self.taskTableWidget)
     self.taskViewWidget = taskviewwidget.TaskViewWidget()
     splitter.addWidget(self.taskViewWidget)
     splitter.setStretchFactor(0, 0)
     splitter.setStretchFactor(1, 1)
     self.setCentralWidget(splitter)
     self.taskViewWidget.hide()
     self.msgLabel = QLabel()
     self.statusBar().addWidget(self.msgLabel)
Esempio n. 11
0
    def __setup_ui(self):
        self.resize(1024, 768)
        self.__setup_menu()

        split = QSplitter()
        self.__yt_tree_widget = YtTreeWidget()
        split.addWidget(self.__yt_tree_widget)

        self.__data_widget = DataWidget()
        split.addWidget(self.__data_widget)
        split.setHandleWidth(2)
        split.setStretchFactor(0, 1)
        split.setStretchFactor(1, 200)

        self.setCentralWidget(split)
Esempio n. 12
0
    def createWidgets(self):
        """
        QtWidgets creation
         _______________________
        |                       |
        |       PyEditor        |
        |_______________________|
        |________QSplitter______|
        |                       |
        |       PyEditor        |
        |_______________________|
        """
        self.srcWidget = EditorWidget(
            self.TEST_DEF_EDITOR,
            "Test Definition:",
            self,
            wrappingText=QtHelper.str2bool(
                Settings.instance().readValue(key='Editor/code-wrapping')))
        self.execWidget = EditorWidget(
            self.TEST_EXEC_EDITOR,
            "Test Execution:",
            self,
            wrappingText=QtHelper.str2bool(
                Settings.instance().readValue(key='Editor/code-wrapping')),
            toolbar=False)

        self.srcEditor = self.srcWidget.editor
        self.execEditor = self.execWidget.editor

        layout = QVBoxLayout()

        hSplitter = QSplitter(self)
        hSplitter.setOrientation(Qt.Vertical)

        hSplitter.addWidget(self.srcWidget)
        hSplitter.addWidget(self.execWidget)
        hSplitter.setContentsMargins(0, 0, 0, 0)
        hSplitter.setStretchFactor(0, 1)

        layout.addWidget(hSplitter)
        layout.setContentsMargins(2, 0, 0, 0)

        self.setLayout(layout)
Esempio n. 13
0
class NetWorthView(AccountSheetView):
    def _setup(self):
        self._setupUi()
        self.sheet = self.nwsheet = NetWorthSheet(self.model.bsheet, view=self.treeView)
        self.graph = self.nwgraph = Chart(self.model.nwgraph, view=self.graphView)
        self.piechart = Chart(self.model.pie, view=self.pieChart)
    
    def _setupUi(self):
        self.resize(558, 447)
        self.mainLayout = QVBoxLayout(self)
        self.mainLayout.setSpacing(0)
        self.mainLayout.setMargin(0)
        self.splitterView = QSplitter()
        self.splitterView.setChildrenCollapsible(False)
        self.splitterView.setOrientation(Qt.Vertical)
        self.subSplitterView = QSplitter()
        self.subSplitterView.setChildrenCollapsible(False)
        self.treeView = TreeView(self)
        self.treeView.setAcceptDrops(True)
        self.treeView.setFrameShape(QFrame.NoFrame)
        self.treeView.setFrameShadow(QFrame.Plain)
        self.treeView.setEditTriggers(QAbstractItemView.EditKeyPressed|QAbstractItemView.SelectedClicked)
        self.treeView.setDragEnabled(True)
        self.treeView.setDragDropMode(QAbstractItemView.InternalMove)
        self.treeView.setUniformRowHeights(True)
        self.treeView.setAllColumnsShowFocus(True)
        self.treeView.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.treeView.header().setStretchLastSection(False)
        self.subSplitterView.addWidget(self.treeView)
        self.pieChart = PieChartView(self)
        self.pieChart.setMinimumSize(300, 0)
        self.subSplitterView.addWidget(self.pieChart)
        self.splitterView.addWidget(self.subSplitterView)
        self.graphView = LineGraphView(self)
        self.graphView.setMinimumSize(0, 200)
        self.splitterView.addWidget(self.graphView)
        self.splitterView.setStretchFactor(0, 1)
        self.splitterView.setStretchFactor(1, 0)
        self.subSplitterView.setStretchFactor(0, 1)
        self.subSplitterView.setStretchFactor(1, 0)
        self.mainLayout.addWidget(self.splitterView)
Esempio n. 14
0
    def g_display(self):
        QWidget.__init__(self)

        layout = QHBoxLayout(self)
        splitter = QSplitter()

        layout.addWidget(splitter)
        splitter.setOrientation(Qt.Horizontal)

        if self.node is not None:
            processus_manager = ModuleProcessusManager()
            evt = processus_manager.get('evt')
            if not self.preview:
                self.evtWidget = evt.getAllEvtFiles()
                if self.evtWidget:
                    splitter.addWidget(self.evtWidget)
                    splitter.setStretchFactor(1, 2)
            else:
                self.evtWidget = evt.previewWidget(long(self.node.this))
                if self.evtWidget:
                    splitter.addWidget(self.evtWidget)
Esempio n. 15
0
class StatusBarWidget(QWidget):
    SplitterHandleStyle = """QSplitter::handle:horizontal {background: 
    qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #eee, stop:1 #ccc);
    border: 1px solid #777; width: 14px; margin-right: 4px; margin-left: 4px;}"""

    def __init__(self, parent=None):
        super(QWidget, self).__init__(parent)
        sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        self.setSizePolicy(sizePolicy)
        self.__hlayout = QHBoxLayout(self)
        self.__hlayout.setSpacing(6)
        self.__hlayout.setSizeConstraint(QLayout.SetMinimumSize)
        self.__hlayout.setMargin(0)
        self.__splitter = QSplitter(Qt.Horizontal, parent)
        self.__splitter.setHandleWidth(12)
        self.__hlayout.addWidget(self.__splitter)

    def addStatusWidget(self, widget, stretch):
        self.__splitter.setStyleSheet(StatusBarWidget.SplitterHandleStyle)
        self.__splitter.addWidget(widget)
        idx = self.__splitter.indexOf(widget)
        self.__splitter.setStretchFactor(idx, stretch)
Esempio n. 16
0
    def setup_layout(self):
        outer_layout = QVBoxLayout()
        outer_layout.addWidget(self.menu_bar)
        outer_layout.setStretch(0, 1)

        h_splitter = QSplitter(self)
        h_splitter.setOrientation(Qt.Horizontal)

        # FIRST COLUMN of h_splitter is chromatogram + peakmap:  ############################

        v_splitter1 = QSplitter(self)
        v_splitter1.setOrientation(Qt.Vertical)
        v_splitter1.addWidget(self.eic_plotter)
        v_splitter1.addWidget(self.peakmap_plotter)
        self.peakmap_plotter.setMinimumSize(250, 200)
        v_splitter1.setStretchFactor(0, 1)
        v_splitter1.setStretchFactor(1, 3)

        h_splitter.addWidget(v_splitter1)
        h_splitter.setStretchFactor(0, 2)

        # SECOND COLUMN of h_splittier holds controlx boxes + mz plot #######################

        v_splitter2 = QSplitter(self)
        v_splitter2.setOrientation(Qt.Vertical)

        v_splitter2.addWidget(self.image_scaling_widget)
        v_splitter2.addWidget(self.spectra_selector_widget)
        v_splitter2.addWidget(self.view_range_widget)
        v_splitter2.addWidget(self.history_list)
        v_splitter2.addWidget(self.mz_plotter)

        v_splitter2.setStretchFactor(0, 0)
        v_splitter2.setStretchFactor(1, 0)
        v_splitter2.setStretchFactor(2, 0)
        v_splitter2.setStretchFactor(3, 0)
        v_splitter2.setStretchFactor(4, 1)

        h_splitter.addWidget(v_splitter2)
        h_splitter.setStretchFactor(1, 1)

        # THIRD COLUMN of h_splittier holds control table + buttons ##########################
        if self.table:
            frame = QFrame(self)
            layout = QVBoxLayout(frame)
            frame.setLayout(layout)
            layout.addWidget(self.table_widget)

            button_row_layout = QHBoxLayout(frame)
            button_row_layout.addWidget(self.select_all_peaks)
            button_row_layout.addWidget(self.unselect_all_peaks)
            button_row_layout.addWidget(self.done_button)

            layout.addLayout(button_row_layout)
            h_splitter.addWidget(frame)
            h_splitter.setStretchFactor(2, 2)

        outer_layout.addWidget(h_splitter)
        self.setLayout(outer_layout)
        outer_layout.setStretch(1, 99)
Esempio n. 17
0
class Window(QMainWindow):

  def __init__(self):
    super(Window, self).__init__()

    central_widget = QWidget()

    self._current_path = None
    self._use_suffix = False

    self._file_model = QFileSystemModel()
    self._file_model.setNameFilters(['*.jpg', '*.png'])
    self._file_model.setNameFilterDisables(False)
    self._file_model.setRootPath(QDir.rootPath())

    self._file_selection_model = QItemSelectionModel(self._file_model)
    self._file_selection_model.currentChanged.connect(self._on_current_file_changed)

    self._file_tree = QTreeView(parent=self)
    self._file_tree.collapsed.connect(self._on_tree_expanded_collapsed)
    self._file_tree.expanded.connect(self._on_tree_expanded_collapsed)
    self._file_tree.setModel(self._file_model)
    self._file_tree.setSelectionModel(self._file_selection_model)
    self._file_tree.setColumnHidden(1, True)
    self._file_tree.setColumnHidden(2, True)
    self._file_tree.setColumnHidden(3, True)
    self._file_tree.header().hide()

    self._viewer = Viewer(Loader(24))

    self._splitter = QSplitter();
    self._splitter.addWidget(self._file_tree)
    self._splitter.addWidget(self._viewer)
    self._splitter.setStretchFactor(0, 0)
    self._splitter.setStretchFactor(1, 1)
    self._splitter.setCollapsible(0, False)

    self._layout = QGridLayout()
    self._layout.addWidget(self._splitter)
    self._switch_to_normal()
    central_widget.setLayout(self._layout)

    self._file_tree.installEventFilter(self);

    self.resize(800, 600)
    self.setWindowTitle('pyQtures')
    self.setCentralWidget(central_widget)
    self.show()

  def eventFilter(self, widget, event):
    if event.type() == QEvent.KeyPress:
      if event.key() == Qt.Key_Tab:
        self._toggle_path_suffix()
        return True
    return QMainWindow.eventFilter(self, widget, event)

  def _toggle_path_suffix(self):
    self._use_suffix = not self._use_suffix
    self._update_path()

  def _switch_to_fullscreen(self):
    self._splitter.widget(0).hide()
    self._layout.setMargin(0)
    self.showFullScreen()

  def _switch_to_normal(self):
    self._splitter.widget(0).show()
    self._layout.setMargin(4)
    self.showNormal()

  def keyPressEvent(self, key_event):  # Signal handler.
    key = key_event.key()
    if self.isFullScreen():
      self._full_screen_key_handler(key)
    else:
      self._normal_key_handler(key)

  def _full_screen_key_handler(self, key):
    if Qt.Key_Escape == key:
      self._switch_to_normal()
    elif Qt.Key_Return == key:
      self._switch_to_normal()
    elif Qt.Key_Up == key:
      self._go_to_sibling_image(-1)
    elif Qt.Key_Down == key:
      self._go_to_sibling_image(1)
    elif Qt.Key_Tab == key:
      self._toggle_path_suffix()

  def _go_to_sibling_image(self, offset):
    current = self._file_selection_model.currentIndex()
    nxt = current.sibling(current.row() + offset, current.column())
    if (nxt.parent() != current.parent()):
      return
    # TODO(eustas): Iterate through dirs?
    self._file_selection_model.setCurrentIndex(nxt, QItemSelectionModel.SelectCurrent)

  def _normal_key_handler(self, key):
    if Qt.Key_Escape == key:
      QCoreApplication.instance().quit()
    elif Qt.Key_Return == key:
      self._switch_to_fullscreen()

  def _on_current_file_changed(self, new_current):
    new_path = self._file_model.filePath(new_current)
    if not self._current_path == new_path:
        self._current_path = new_path
        self._update_path()

  def _update_path(self):
    if not self._use_suffix:
      self._viewer.set_path(self._current_path)
      return

    self._viewer.reset_path()
    if not self._current_path:
      return

    selected_file = QFileInfo(self._current_path)
    if not selected_file.exists():
      return

    selected_dir = selected_file.absoluteDir()
    file_name = selected_file.fileName()
    if not selected_dir.exists():
      return

    if not selected_dir.cd('converted'):
      return

    suffixed_path = selected_dir.absoluteFilePath(file_name)
    self._viewer.set_path(suffixed_path)

  def _on_tree_expanded_collapsed(self, unused_index):
    QTimer.singleShot(1, lambda: self._file_tree.resizeColumnToContents(0))
Esempio n. 18
0
    def __init__(self):
        super(CMakeToolView, self).__init__(None)
        self.toolView = kate.mainInterfaceWindow().createToolView(
            'cmake_utils'
          , kate.Kate.MainWindow.Bottom
          , KIcon('cmake').pixmap(32, 32)
          , i18nc('@title:tab', 'CMake')
          )
        self.toolView.installEventFilter(self)
        # By default, the toolview has box layout, which is not easy to delete.
        # For now, just add an extra widget.
        tabs = QTabWidget(self.toolView)
        # Make a page to view cmake cache
        self.cacheViewPage = uic.loadUi(
            os.path.join(os.path.dirname(__file__), settings.CMAKE_TOOLVIEW_CACHEVIEW_UI)
          )
        self.cacheViewPage.buildDir.setText(kate.sessionConfiguration[settings.PROJECT_DIR])
        # TODO It seems not only KTextEditor's SIP files are damn out of date...
        # KUrlRequester actually *HAS* setPlaceholderText() method... but damn SIP
        # files for KIO are damn out of date either! A NEW BUG NEEDS TO BE ADDED!
        # (but I have fraking doubts that it will be closed next few damn years)
        #
        #self.buildDir.setPlaceholderText(i18nc('@info', 'Project build directory'))
        self.cacheViewPage.buildDir.lineEdit().setPlaceholderText(
            i18nc('@info/plain', 'Project build directory')
          )
        self.cacheViewPage.buildDir.setMode(
            KFile.Mode(KFile.Directory | KFile.ExistingOnly | KFile.LocalOnly)
          )
        self.cacheViewPage.cacheItems.sortItems(0, Qt.AscendingOrder)
        self.cacheViewPage.cacheFilter.setTreeWidget(self.cacheViewPage.cacheItems)
        tabs.addTab(self.cacheViewPage, i18nc('@title:tab', 'CMake Cache Viewer'))
        # Make a page w/ cmake help
        splitter = QSplitter(Qt.Horizontal, tabs)
        self.vewHelpPage = uic.loadUi(
            os.path.join(os.path.dirname(__file__), settings.CMAKE_TOOLVIEW_HELP_UI)
          )
        self.vewHelpPage.helpFilter.setTreeWidget(self.vewHelpPage.helpTargets)
        self.updateHelpIndex()                              # Prepare Help view
        self.helpPage = QTextBrowser(splitter)
        self.helpPage.setReadOnly(True)
        self.helpPage.setOpenExternalLinks(False)
        self.helpPage.setOpenLinks(False)
        splitter.addWidget(self.vewHelpPage)
        splitter.addWidget(self.helpPage)
        splitter.setStretchFactor(0, 10)
        splitter.setStretchFactor(1, 20)
        tabs.addTab(splitter, i18nc('@title:tab', 'CMake Help'))
        # Make a page w/ some instant settings
        self.cfgPage = uic.loadUi(
            os.path.join(os.path.dirname(__file__), settings.CMAKE_TOOLVIEW_SETTINGS_UI)
          )
        self.cfgPage.mode.setChecked(kate.sessionConfiguration[settings.TOOLVIEW_ADVANCED_MODE])
        self.cfgPage.htmlize.setChecked(kate.sessionConfiguration[settings.TOOLVIEW_BEAUTIFY])
        tabs.addTab(self.cfgPage, i18nc('@title:tab', 'Tool View Settings'))

        # Connect signals
        self.cacheViewPage.cacheItems.itemActivated.connect(self.insertIntoCurrentDocument)
        self.cacheViewPage.buildDir.returnPressed.connect(self.updateCacheView)
        self.cacheViewPage.buildDir.urlSelected.connect(self.updateCacheView)
        self.cfgPage.mode.toggled.connect(self.updateCacheView)
        self.cfgPage.mode.toggled.connect(self.saveSettings)
        self.cfgPage.htmlize.toggled.connect(self.updateHelpText)
        self.cfgPage.htmlize.toggled.connect(self.saveSettings)
        self.vewHelpPage.helpTargets.itemActivated.connect(self.updateHelpText)
        self.vewHelpPage.helpTargets.itemDoubleClicked.connect(self.insertHelpItemIntoCurrentDocument)
        self.helpPage.anchorClicked.connect(openDocument)

        # Refresh the cache view
        self._updateCacheView(self.cacheViewPage.buildDir.text())
Esempio n. 19
0
class DSBrowser(QWidget):
    """browser for datastorage databases
       Nodes are identified by a string, containing fields separated by '|'.
       - first filed is a capital letter:
       'R'oot, 'P'roject, sensor'G'roup, 'S'ensor and 'C'hart
       - second field is the database folder
       - third filed is the path of the node in the database
       - for charts the fourth field is the chart name (third is path of sensorgroup in this case)
    """
    def __init__(self):
        QWidget.__init__(self)
        self.layout = QVBoxLayout(self)
        self.layout.setSpacing(0)
        self.layout.setMargin(0)

        self.toolBar = QFrame(self)
        self.toolBarLayout = QHBoxLayout(self.toolBar)
        self.toolBarLayout.setMargin(2)
        self.toolBarLayout.setSpacing(2)
        self.layout.addWidget(self.toolBar)

        self.loadButton = QToolButton(self.toolBar)
        self.loadButton.setText(QCoreApplication.translate('DataStorageBrowser', 'Open...'))
        self.loadButton.setIcon(QIcon(QPixmap(SimuVis4.Icons.fileOpen)))
        self.loadButton.setToolTip(QCoreApplication.translate('DataStorageBrowser', 'Open a datastorage database'))
        self.toolBarLayout.addWidget(self.loadButton)
        self.connect(self.loadButton, SIGNAL('pressed()'), self.loadDatabase)

        self.dropButton = QToolButton(self.toolBar)
        self.dropButton.setText(QCoreApplication.translate('DataStorageBrowser', 'Close All'))
        self.dropButton.setIcon(QIcon(QPixmap(SimuVis4.Icons.clear)))
        self.dropButton.setToolTip(QCoreApplication.translate('DataStorageBrowser', 'Drop all open databases'))
        self.toolBarLayout.addWidget(self.dropButton)
        self.connect(self.dropButton, SIGNAL('pressed()'), self.dropDatabases)
        self.dropButton.setEnabled(False)

        self.toolBarLayout.addStretch(100)

        self.splitter = QSplitter(self)
        self.splitter.setOrientation(Qt.Vertical)
        self.treeView = QTreeView(self.splitter)
        self.treeView.setAlternatingRowColors(True)
        self.treeView.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.treeView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.treeView.setAutoExpandDelay(500)
        self.textBrowser = QTextBrowser(self.splitter)
        self.layout.addWidget(self.splitter)
        self.splitter.setStretchFactor(0, 60)
        self.splitter.setStretchFactor(1, 40)
        self.model = DSModel()
        self.treeView.setModel(self.model)
        self.treeView.setSortingEnabled(True)
        self.treeView.expandAll()
        self.connect(self.treeView.selectionModel(), SIGNAL("currentChanged(QModelIndex, QModelIndex)"), self.showItem)
        self.connect(self.treeView, SIGNAL("doubleClicked(QModelIndex)"), self.itemAction)
        self.connect(self.treeView, SIGNAL("customContextMenuRequested(QPoint)"), self.showContextMenu)
        self.selectedNode = None
        self.selectedMI = None


    def loadDatabase(self, dn=None):
        """load a database"""
        if not dn:
            dn = QFileDialog.getExistingDirectory(self, QCoreApplication.translate('DataStorageBrowser',
                "Select a folder containing a datastorage database"), SimuVis4.Globals.defaultFolder)
            if not dn.isEmpty():
                dn = unicode(dn)
                SimuVis4.Globals.defaultFolder = dn
            else:
                return
        self.model.addDatabase(dn)
        self.treeView.expandToDepth(1)


    def dropDatabases(self):
        # FIXME: implement it
        pass


    def showItem(self, mi, pr):
        """show the item at model index mi"""
        t, n = self.model.dsNode(mi)
        txt = ""
        if t == 'R':
            # FIXME: no metadata?
            txt = rootInfo.substitute(name=n.name, title=escape(n.title), folder=n.h5dir, projects=len(n)) # + formatMetaData(n)
        elif t == 'P':
            txt = projectInfo.substitute(name=n.name, title=escape(n.title), groups=len(n)) + formatMetaData(n)
        elif t == 'G':
            txt = groupInfo.substitute(name=n.name, title=escape(n.title), sensors=len(n), charts=len(n.charts)) + formatMetaData(n)
        elif t == 'S':
            txt = sensorInfo.substitute(name=n.name, title=escape(n.title), start=n.timegrid.start, stop=n.timegrid.stop,
                step=n.timegrid.step, length=n.datalen()) + formatMetaData(n)
        elif t == 'C':
            txt = chartInfo.substitute(name=n.name)
        self.textBrowser.setText(txt)


    def itemAction(self, mi):
        """default action (on doubleclick) for item at model index mi"""
        t, n = self.model.dsNode(mi)
        if t == 'R':
            pass
        elif t == 'P':
            pass
        elif t == 'G':
            pass
        elif t == 'S':
            print n
            self.showQwtPlot(n)
        elif t == 'C':
            self.showMplChart(n)


    def showContextMenu(self, pos):
        """show context menu for item at pos"""
        mi = self.treeView.indexAt(pos)
        t, n = self.model.dsNode(mi)
        self.selectedNode = n
        self.selectedMI = mi
        m = QMenu()
        if t in 'RPGS':
            p = m.addAction(QCoreApplication.translate('DataStorageBrowser', 'Edit metadata'), self.editMetadata)
        if t == 'R':
            pass
        elif t == 'P':
            pass
        elif t == 'G':
            m.addAction(QCoreApplication.translate('DataStorageBrowser', 'Add Chart'), self.newChart)
        elif t == 'S':
            m.addAction(QCoreApplication.translate('DataStorageBrowser', 'Plot (Qwt)'), self.showQwtPlot)
        elif t == 'C':
            m.addAction(QCoreApplication.translate('DataStorageBrowser', 'Show'), self.showMplChart)
            m.addAction(QCoreApplication.translate('DataStorageBrowser', 'Delete'), self.deleteItem)
        a = m.exec_(self.treeView.mapToGlobal(pos))


    def showMplChart(self, node=None):
        if node is None:
            node = self.selectedNode
        showChartMplWindow(node, maximized=showChartMaximized)


    def showQwtPlot(self, node=None):
        if node is None:
            node = self.selectedNode
        showQwtPlotWindow(node, maximized=showChartMaximized)


    def editMetadata(self, node=None):
        if node is None:
            node = self.selectedNode
        editMetadata(node)


    def newChart(self, mi=None):
        """add a chart to sensorgroup at mi using the wizard"""
        if mi is None:
            mi = self.selectedMI
        showNewChartWizard(self.model, mi)

    def deleteItem(self, mi=None):
        """delete the item at mi"""
        if mi is None:
            mi = self.selectedMI
        self.model.deleteItem(mi)
Esempio n. 20
0
    def __init__(self, parent, logger):
        super(MembersWidget, self).__init__(parent)

        self.logger = logger
        layout = QVBoxLayout(self)
        layout.setSpacing(0)

        self.dropdown_members_dict = {}
        self.dropdown_members_model = DropdownModel(get_peers(), self.logger)
        self.dropdown_members = QComboBox(self)
        self.dropdown_members.setModel(self.dropdown_members_model)

        topLayout = QHBoxLayout()
        topLayout.setSpacing(10)
        topLayout.addWidget(self.dropdown_members, 1)
        self.requestLogsButton = QPushButton("Request Logfiles", self)
        topLayout.addWidget(self.requestLogsButton)
        layout.addLayout(topLayout)

        layout.addWidget(QLabel("Member Information:", self))
        self.memberInformationTable = QTreeWidget(self)
        self.memberInformationTable.setMaximumHeight(65)
        self.memberInformationTable.setSelectionMode(QTreeWidget.NoSelection)
        layout.addWidget(self.memberInformationTable, 0)

        layout.addWidget(QLabel("Send Message:", self))

        sendMessageLayout = QHBoxLayout()
        sendMessageLayout.setSpacing(10)
        messageInput = HistoryLineEdit(self, "Enter a message")
        self.sendMessageButton = QPushButton("Send", self)
        sendMessageLayout.addWidget(messageInput, 1)
        sendMessageLayout.addWidget(self.sendMessageButton)
        layout.addLayout(sendMessageLayout)

        layout.addWidget(QLabel("Log files:", self))
        logSplitter = QSplitter(Qt.Horizontal, self)

        logListWidget = QWidget(self)
        logListLayout = QVBoxLayout(logListWidget)
        logListLayout.setContentsMargins(0, 0, 0, 0)

        self.log_tree_view = QTreeWidget(logSplitter)
        self.log_tree_view.setAlternatingRowColors(True)
        self.log_tree_view.setColumnCount(1)
        self.log_tree_view.setHeaderHidden(True)
        self.log_tree_view.setItemsExpandable(False)
        self.log_tree_view.setIndentation(0)

        logListLayout.addWidget(self.log_tree_view, 1)

        logListBottomLayout = QHBoxLayout()
        self.logSizeLabel = QLabel(logListWidget)
        logListBottomLayout.addWidget(self.logSizeLabel, 1)

        self.clearLogsButton = QPushButton("Clear", logListWidget)
        self.clearLogsButton.setEnabled(False)
        self.clearLogsButton.clicked.connect(self.clearLogs)
        logListBottomLayout.addWidget(self.clearLogsButton, 0)

        logListLayout.addLayout(logListBottomLayout)

        logSplitter.addWidget(logListWidget)

        self.log_area = QTextEdit(logListWidget)
        self.log_area.setLineWrapMode(QTextEdit.WidgetWidth)
        self.log_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.log_area.setReadOnly(True)
        logSplitter.addWidget(self.log_area)

        logSplitter.setStretchFactor(0, 0)
        logSplitter.setStretchFactor(1, 1)

        layout.addWidget(logSplitter, 1)

        self.memberSelectionChanged()
        self.log_tree_view.selectionModel().selectionChanged.connect(self.displaySelectedLogfile)
        self.dropdown_members.currentIndexChanged.connect(self.memberSelectionChanged)
        self.requestLogsButton.clicked.connect(self.requestLogClicked)
        self.sendMessageButton.clicked.connect(partial(self.sendMessageToMember, messageInput))
        messageInput.returnPressed.connect(partial(self.sendMessageToMember, messageInput))

        get_notification_center().connectPeerAppended(self.dropdown_members_model.externalRowAppended)
        get_notification_center().connectPeerUpdated(self.dropdown_members_model.externalRowUpdated)
        get_notification_center().connectPeerRemoved(self.dropdown_members_model.externalRowRemoved)
        get_notification_center().connectPeerUpdated(self.updateMemberInformation)
Esempio n. 21
0
    def setup_layout(self):
        outer_layout = QVBoxLayout()
        outer_layout.addWidget(self.menu_bar)
        outer_layout.setStretch(0, 1)

        h_splitter = QSplitter(self)
        h_splitter.setOrientation(Qt.Horizontal)

        # FIRST COLUMN of h_splitter is chromatogram + peakmap:  ############################

        v_splitter1 = QSplitter(self)
        v_splitter1.setOrientation(Qt.Vertical)
        v_splitter1.addWidget(self.eic_plotter)
        v_splitter1.addWidget(self.peakmap_plotter)
        self.peakmap_plotter.setMinimumSize(250, 200)
        v_splitter1.setStretchFactor(0, 1)
        v_splitter1.setStretchFactor(1, 3)

        h_splitter.addWidget(v_splitter1)
        h_splitter.setStretchFactor(0, 2)

        # SECOND COLUMN of h_splittier holds controlx boxes + mz plot #######################

        v_splitter2 = QSplitter(self)
        v_splitter2.setOrientation(Qt.Vertical)

        v_splitter2.addWidget(self.image_scaling_widget)
        v_splitter2.addWidget(self.spectra_selector_widget)
        v_splitter2.addWidget(self.view_range_widget)
        v_splitter2.addWidget(self.history_list)
        v_splitter2.addWidget(self.mz_plotter)

        v_splitter2.setStretchFactor(0, 0)
        v_splitter2.setStretchFactor(1, 0)
        v_splitter2.setStretchFactor(2, 0)
        v_splitter2.setStretchFactor(3, 0)
        v_splitter2.setStretchFactor(4, 1)

        h_splitter.addWidget(v_splitter2)
        h_splitter.setStretchFactor(1, 1)

        # THIRD COLUMN of h_splittier holds control table + buttons ##########################
        if self.table:
            frame = QFrame(self)
            layout = QVBoxLayout(frame)
            frame.setLayout(layout)
            layout.addWidget(self.table_widget)

            button_row_layout = QHBoxLayout(frame)
            button_row_layout.addWidget(self.select_all_peaks)
            button_row_layout.addWidget(self.unselect_all_peaks)
            button_row_layout.addWidget(self.done_button)

            layout.addLayout(button_row_layout)
            h_splitter.addWidget(frame)
            h_splitter.setStretchFactor(2, 2)

        outer_layout.addWidget(h_splitter)
        self.setLayout(outer_layout)
        outer_layout.setStretch(1, 99)
class WWorkspace(QWidget):
    """
    Workspace widget
    """
    WORKSPACE = 0
    UpdateWindowTitle = pyqtSignal(str)
    RecentFile = pyqtSignal(dict)
    BusyCursor = pyqtSignal()
    ArrowCursor = pyqtSignal()

    def __init__(self, parent=None):
        """
        Constructs WWorkspace widget

        Signals emited:
         * updateWindowTitle

        @param parent: 
        @type parent:
        """
        QWidget.__init__(self, parent)
        self.parent = parent
        self.type = self.WORKSPACE
        self.name = self.tr('Workspace')

        # create each part
        WRepositories.initialize(parent=self)
        WDocumentViewer.initialize(parent=self,
                                   iRepo=WRepositories.instance(),
                                   lRepo=WRepositories.LocalRepository,
                                   rRepo=WRepositories.RemoteRepository)
        WDocumentProperties.initialize(parent=self,
                                       iRepo=WRepositories.instance(),
                                       lRepo=WRepositories.LocalRepository,
                                       rRepo=WRepositories.RemoteRepository)
        WHelper.initialize(parent=self)

        # splitter state
        self.splitterState = None
        self.splitterHelperState = None

        # create widget
        self.createWidgets()
        self.createActions()
        self.creationConnections()

    def createWidgets(self):
        """
        QtWidgets creation
           _________                _______________________      _________ 
          /         \__________    |                       |    /         \__
         |                     | Q |                       | Q |             |
         |   WRepositories     | S |                       | S |             |
         |                     | p |                       | p |             |
         |_____________________| l |                       | l |             |  
           _____QSplitter        i |     WDocumentViewer   | i |   WHelper   |
          /         \__________  t |                       | t |             |
         |                     | t |                       | t |             |
         | WDocumentProperties | e |                       | e |             |
         |                     | r |                       | r |             |
         |_____________________|   |_______________________|   |_____________|
        """

        self.wCursorPosition = WCursorPosition(self)
        self.parent.addWidgetToStatusBar(self.wCursorPosition)
        WDocumentProperties.instance().setDisabled(True)

        layout = QHBoxLayout(self)

        #  properties | viewer | helper
        self.vSplitter = QSplitter(self)

        if not QtHelper.str2bool(
                Settings.instance().readValue(key='View/tab-left')):
            self.hSplitter = QSplitter(self)
            self.hSplitter.setOrientation(Qt.Vertical)

            self.hSplitter.addWidget(WRepositories.instance())
            self.hSplitter.addWidget(WDocumentProperties.instance())
            self.hSplitter.setContentsMargins(0, 0, 0, 0)

            self.vSplitter.addWidget(self.hSplitter)
        else:
            WRepositories.instance().hideWidgetsHeader()
            WDocumentProperties.instance().hideWidgetsHeader()

            self.leftTab = QTabWidget(self)
            self.leftTab.addTab(WRepositories.instance(),
                                QIcon(":/folders.png"),
                                self.tr("Repositories"))
            self.leftTab.addTab(WDocumentProperties.instance(),
                                QIcon(":/controls.png"),
                                self.tr("Test Properties"))
            self.vSplitter.addWidget(self.leftTab)

        self.vSplitter.addWidget(WDocumentViewer.instance())
        self.vSplitter.setStretchFactor(1, 1)

        layout.addWidget(self.vSplitter)

        self.hSplitter2 = QSplitter(self)
        self.hSplitter2.setOrientation(Qt.Vertical)

        self.vSplitter.addWidget(self.hSplitter2)
        self.hSplitter2.addWidget(WHelper.instance())

        self.setLayout(layout)

    def creationConnections(self):
        """
        QtSignals connection:
         * WRepositories <=> WDocumentViewer.newTab
         * WDocumentViewer <=> cursorPositionChanged
         * WDocumentViewer <=> focusChanged
        """
        WRepositories.instance().local().OpenFile.connect(
            WDocumentViewer.instance().newTab)

        WDocumentViewer.instance().CursorPositionChanged.connect(
            self.cursorPositionChanged)
        WDocumentViewer.instance().TotalLinesChanged.connect(
            self.totalLinesChanged)
        WDocumentViewer.instance().FocusChanged.connect(self.focusChanged)

        WDocumentViewer.instance().BusyCursor.connect(self.emitBusy)
        WDocumentViewer.instance().ArrowCursor.connect(self.emitIdle)
        WDocumentViewer.instance().CurrentDocumentChanged.connect(
            self.currentDocumentChanged)
        WDocumentViewer.instance().DocumentOpened.connect(self.documentOpened)
        WDocumentViewer.instance().UpdateWindowTitle.connect(
            self.updateWindowTitle)
        WDocumentViewer.instance().DocumentViewerEmpty.connect(
            self.documentViewerEmpty)

        # from testplan when the test selection changed in the tree
        WDocumentViewer.instance().PropertiesChanged.connect(
            self.propertiesChanged)

        if WRepositories.instance().localConfigured != "Undefined":
            if RCI.instance().isAuthenticated():
                WDocumentViewer.instance().RefreshLocalRepository.connect(
                    WRepositories.instance().localRepository.refreshAll)
                WDocumentProperties.instance().RefreshLocalRepository.connect(
                    WRepositories.instance().localRepository.refreshAll)
        WDocumentViewer.instance().RecentFile.connect(self.recentFileUpdated)

        WHelper.instance().ShowAssistant.connect(self.onEnterAssistant)
        WHelper.instance().HideAssistant.connect(self.onLeaveAssistant)

        # new in v16
        WDocumentViewer.instance().ShowPropertiesTab.connect(
            self.onShowPropertiesTab)

    def onShowPropertiesTab(self):
        """
        On show properties tabulation
        """
        if QtHelper.str2bool(
                Settings.instance().readValue(key='View/tab-left')):
            self.leftTab.setCurrentIndex(TAB_PROPERTIES)

    def onEnterAssistant(self):
        """
        On mouse enter in the online helper
        """
        pass

    def onLeaveAssistant(self):
        """
        On mouse leave in the online helper
        """
        pass

    def createActions(self):
        """
        Create qt actions
        """
        self.hideDeveloperModeAction = QtHelper.createAction(
            self,
            self.tr("Developer"),
            self.hideDeveloperMode,
            checkable=True,
            icon=QIcon(":/window-fit.png"),
            shortcut=Settings.instance().readValue(
                key='KeyboardShorcuts/developer'),
            tip=self.tr('Fit the document viewer to maximize the editor area'))
        WDocumentViewer.instance().addActionToolbar(
            action=self.hideDeveloperModeAction)

    def emitBusy(self):
        """
        Emit busy
        """
        self.BusyCursor.emit()

    def emitIdle(self):
        """
        Emit idle
        """
        self.ArrowCursor.emit()

    def hideDeveloperMode(self):
        """
        Hide developer mode
        """
        if not self.hideDeveloperModeAction.isChecked():
            Settings.instance().setValue(key='View/developer', value='False')
            self.deactiveDeveloperView()
        else:
            Settings.instance().setValue(key='View/developer', value='True')
            self.activeDeveloperView()

    def activeDeveloperView(self):
        """
        Activate developer view
        """
        self.splitterState = self.vSplitter.saveState()
        self.vSplitter.setSizes([0, self.vSplitter.sizes()[1], 0])

    def deactiveDeveloperView(self):
        """
        Deactive developer view
        """
        if self.splitterState is not None:
            self.vSplitter.restoreState(self.splitterState)

    def mainSplitterMoved(self, index, pos):
        """
        Memorize the new position of the splitter
        """
        Settings.instance().setValue(key='View/helper-pos',
                                     value=self.vSplitter.sizes()[2])

    def hideHelper(self):
        """
        Hide assistant
        """
        self.splitterHelperState = self.vSplitter.saveState()
        self.vSplitter.setSizes(
            [self.vSplitter.sizes()[0],
             self.vSplitter.sizes()[1], 0])

    def showHelper(self):
        """
        Show assistant
        """
        if self.splitterHelperState is not None:
            self.vSplitter.restoreState(self.splitterHelperState)

    def documentViewerEmpty(self):
        """
        Called to deactivate the WDocumentProperties widget
        Hide the WCursorPosition widget in the status bar
        """
        WDocumentProperties.instance().clear()
        WDocumentProperties.instance().setDisabled(True)
        self.hideStatusBar()
        WDocumentViewer.instance().findWidget.hide()

    def currentDocumentChanged(self, wdocument):
        """
        Called when the current document is changed

        @param wdocument:
        @type wdocument:
        """
        # hide cursor position widget on disconnection or on the welcome page
        if isinstance(wdocument, WDocumentViewer.WelcomePage):
            self.hideStatusBar()

        if not RCI.instance().isAuthenticated():
            WDocumentProperties.instance().setDisabled(True)
            return

        # test properties uneeded for test config, test adapter and library adapters
        # and welcome page
        if isinstance(wdocument, WDocumentViewer.WelcomePage):

            WDocumentProperties.instance().setDisabled(True)
            WDocumentProperties.instance().clear()
        elif isinstance(wdocument, TestConfig.WTestConfig) or isinstance(wdocument, TestAdapter.WTestAdapter) \
                or isinstance(wdocument, TestTxt.WTestTxt)  or isinstance(wdocument, TestLibrary.WTestLibrary) \
                    or isinstance(wdocument, TestPng.WTestPng) :
            WDocumentProperties.instance().setDisabled(True)
            WDocumentProperties.instance().clear()
        else:
            WDocumentProperties.instance().setDocument(wdoc=wdocument)
            WDocumentProperties.instance().setDisabled(False)
            WDocumentProperties.instance().addDescriptions(wdoc=wdocument)
            WDocumentProperties.instance().addParameters(wdoc=wdocument)
            if not isinstance(wdocument, TestData.WTestData):
                WDocumentProperties.instance().addParametersOutput(
                    wdoc=wdocument)
                WDocumentProperties.instance().addProbes(wdoc=wdocument)
                WDocumentProperties.instance().addAgents(wdoc=wdocument)
            WDocumentViewer.instance().updateActions(wdocument=wdocument)

            if isinstance(wdocument, TestData.WTestData):
                WDocumentProperties.instance().disableOutputParameters()
                WDocumentProperties.instance().disableAgents()
                WDocumentProperties.instance().disableProbes()
            else:
                WDocumentProperties.instance().enableOutputParameters()
                WDocumentProperties.instance().enableProbes()
                WDocumentProperties.instance().enableAgents()

            if not isinstance(wdocument, TestAbstract.WTestAbstract):
                WDocumentProperties.instance().disableSteps()
                WDocumentProperties.instance().disableAdapters()
                WDocumentProperties.instance().disableLibraries()
            else:
                WDocumentProperties.instance().addSteps(wdoc=wdocument)
                WDocumentProperties.instance().enableSteps()
                WDocumentProperties.instance().addAdapters(wdoc=wdocument)
                WDocumentProperties.instance().enableAdapters()
                WDocumentProperties.instance().addLibraries(wdoc=wdocument)
                WDocumentProperties.instance().enableLibraries()

            if isinstance(wdocument, TestUnit.WTestUnit) or isinstance(
                    wdocument, TestSuite.WTestSuite):
                WDocumentProperties.instance().enableMarkUnused()
            else:
                WDocumentProperties.instance().disableMarkUnused()

        # disable/enable status bar
        if isinstance(wdocument, TestConfig.WTestConfig) \
                or isinstance(wdocument, TestPlan.WTestPlan) \
                or isinstance(wdocument, TestPng.WTestPng) \
                or  isinstance(wdocument, TestAbstract.WTestAbstract) \
                or isinstance(wdocument, WDocumentViewer.WelcomePage) :
            self.hideStatusBar()
        else:
            self.showStatusBar()
            self.wCursorPosition.setNumberLines(nb=wdocument.editor().lines())

    def propertiesChanged(self, properties, isRoot, testId):
        """
        Called when document propertis changed

        @param properties:
        @param properties: dict

        @param isRoot: 
        @type isRoot:
        """
        if isRoot:
            WDocumentProperties.instance().addDescriptions(wdoc=properties)
            WDocumentProperties.instance().addParameters(wdoc=properties)
            WDocumentProperties.instance().addParametersOutput(wdoc=properties)
            WDocumentProperties.instance().addAgents(wdoc=properties)
            WDocumentProperties.instance().addProbes(wdoc=properties)
            WDocumentProperties.instance().probes.setEnabled(True)
        else:
            WDocumentProperties.instance().addParameters(wdoc=properties)
            WDocumentProperties.instance().addAgents(wdoc=properties)
            WDocumentProperties.instance().addParametersOutput(wdoc=properties)
            WDocumentProperties.instance().probes.clear()
            WDocumentProperties.instance().probes.setEnabled(False)

        # new in v19
        WDocumentProperties.instance().updateCache(properties, isRoot, testId)

    def documentOpened(self, wdocument):
        """
        Called when a document is opened

        @param wdocument:
        @type wdocument:
        """
        WDocumentProperties.instance().setEnabled(True)
        self.currentDocumentChanged(wdocument=wdocument)

    def updateWindowTitle(self, windowTitle):
        """
        Emit the signal "updateWindowTitle" to update 
        the title of the application

        @param windowTitle: new window title
        @type windowTitle: string
        """
        self.UpdateWindowTitle.emit(windowTitle)

    def recentFileUpdated(self, fileDescription):
        """
        Emit the signal "recentFile" to update 
        the title of the application

        @param windowTitle: file descr with the complete path and type
        @type windowTitle: string
        """
        self.RecentFile.emit(fileDescription)

    def focusChanged(self, wdocument):
        """
        Called when the focus of the WDocumentViewer is changed

        @param wdocument:
        @type wdocument:
        """
        WDocumentViewer.instance().updateActions(wdocument=wdocument)
        self.wCursorPosition.setNumberLines(nb=wdocument.editor().lines())

    def totalLinesChanged(self, nb):
        """
        This function is automaticaly called when the cursor changed in both editors
        and enables to update the cursor's position in the widget WCursorPosition

        @param ln: line index
        @type ln: Integer
        
        @param col: column index
        @type col: Integer
        """
        self.wCursorPosition.setNumberLines(nb=nb)

    def cursorPositionChanged(self, ln, col):
        """
        This function is automaticaly called when the cursor changed in both editors
        and enables to update the cursor's position in the widget WCursorPosition

        @param ln: line index
        @type ln: Integer
        
        @param col: column index
        @type col: Integer
        """
        self.wCursorPosition.cursorPositionChanged(ln, col)

    def showStatusBar(self):
        """
        Show WCursorPosition widget
        """
        self.wCursorPosition.show()

    def hideStatusBar(self):
        """
        Hide WCursorPosition widget
        """
        self.wCursorPosition.hide()
Esempio n. 23
0
class DSBrowser(QWidget):
    """browser for datastorage databases
       Nodes are identified by a string, containing fields separated by '|'.
       - first filed is a capital letter:
       'R'oot, 'P'roject, sensor'G'roup, 'S'ensor and 'C'hart
       - second field is the database folder
       - third filed is the path of the node in the database
       - for charts the fourth field is the chart name (third is path of sensorgroup in this case)
    """

    def __init__(self):
        QWidget.__init__(self)
        self.layout = QVBoxLayout(self)
        self.layout.setSpacing(0)
        self.layout.setMargin(0)

        self.toolBar = QFrame(self)
        self.toolBarLayout = QHBoxLayout(self.toolBar)
        self.toolBarLayout.setMargin(2)
        self.toolBarLayout.setSpacing(2)
        self.layout.addWidget(self.toolBar)

        self.loadButton = QToolButton(self.toolBar)
        self.loadButton.setText(QCoreApplication.translate("DataStorageBrowser", "Open..."))
        self.loadButton.setIcon(QIcon(QPixmap(SimuVis4.Icons.fileOpen)))
        self.loadButton.setToolTip(QCoreApplication.translate("DataStorageBrowser", "Open a datastorage database"))
        self.toolBarLayout.addWidget(self.loadButton)
        self.connect(self.loadButton, SIGNAL("pressed()"), self.loadDatabase)

        self.expandButton = QToolButton(self.toolBar)
        self.expandButton.setText("Expand/Collapse")
        self.expandButton.setIcon(QIcon(QPixmap(Icons.exp_col)))
        self.expandButton.setToolTip(
            QCoreApplication.translate("DataStorageBrowser", "Expand or collapse the whole tree")
        )
        self.toolBarLayout.addWidget(self.expandButton)
        self.connect(self.expandButton, SIGNAL("pressed()"), self.expandCollapseAll)

        self.searchInput = MyLineEdit(self.toolBar)
        self.searchInput.setText(QCoreApplication.translate("DataStorageBrowser", "Enter search text here"))
        self.searchInput.setToolTip(
            QCoreApplication.translate(
                "DataStorageBrowser", "Enter search text using wildcards here, press ENTER again to go to next match!"
            )
        )
        self.toolBarLayout.addWidget(self.searchInput, 100)
        self.connect(self.searchInput, SIGNAL("returnPressed()"), self.searchItem)

        self.helpButton = QToolButton(self.toolBar)
        self.helpButton.setText(QCoreApplication.translate("DataStorageBrowser", "Help"))
        self.helpButton.setIcon(QIcon(QPixmap(SimuVis4.Icons.help)))
        self.helpButton.setToolTip(QCoreApplication.translate("DataStorageBrowser", "Show help for DataStorageBrowser"))
        self.toolBarLayout.addWidget(self.helpButton)
        self.connect(self.helpButton, SIGNAL("pressed()"), self.showHelp)

        self.splitter = QSplitter(self)
        self.splitter.setOrientation(Qt.Vertical)
        self.treeView = QTreeView(self.splitter)
        self.treeView.setAlternatingRowColors(True)
        self.treeView.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.treeView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.treeView.setAutoExpandDelay(500)
        self.textBrowser = QTextBrowser(self.splitter)
        self.layout.addWidget(self.splitter)
        self.splitter.setStretchFactor(0, 60)
        self.splitter.setStretchFactor(1, 40)
        self.model = DSModel()
        self.treeView.setModel(self.model)
        self.treeView.setSortingEnabled(True)
        self.treeView.expandAll()
        self.connect(self.treeView.selectionModel(), SIGNAL("currentChanged(QModelIndex, QModelIndex)"), self.showItem)
        self.connect(self.treeView, SIGNAL("doubleClicked(QModelIndex)"), self.itemAction)
        self.connect(self.treeView, SIGNAL("customContextMenuRequested(QPoint)"), self.showContextMenu)
        self.selectedNode = None
        self.selectedMI = None
        self.searchText = ""
        self.searchResults = []
        self.collExpand = SimuVis4.Misc.Switcher()

        self.statusBar = SimuVis4.Globals.mainWin.statusBar()

    def loadDatabase(self, dn=None):
        """load a database"""
        if not dn:
            dn = QFileDialog.getExistingDirectory(
                self,
                QCoreApplication.translate("DataStorageBrowser", "Select a folder containing a datastorage database"),
                SimuVis4.Globals.defaultFolder,
            )
            if not dn.isEmpty():
                dn = unicode(dn)
                SimuVis4.Globals.defaultFolder = dn
            else:
                return
        self.model.addDatabase(dn)
        self.treeView.collapseAll()
        self.treeView.expandToDepth(SimuVis4.Globals.config.getint("datastoragebrowser", "expand_tree_depth"))
        self.treeView.resizeColumnToContents(0)

    def showHelp(self):
        SimuVis4.HelpBrowser.showHelp("/plugin/DataStorageBrowser/index.html")

    def showItem(self, mi, pr):
        """show the item at model index mi"""
        t, n = self.model.dsNode(mi)
        txt = ""
        if t == "R":
            txt = rootInfo.substitute(
                name=n.name, title=escape(n.title), folder=n.h5dir, projects=len(n)
            ) + formatMetaData(n)
        elif t == "P":
            txt = projectInfo.substitute(
                name=n.name, path=escape(n.parent.name), title=escape(n.title), groups=len(n)
            ) + formatMetaData(n)
        elif t == "G":
            txt = groupInfo.substitute(
                name=n.name,
                path="/".join(n.path.split("/")[:-1]),
                title=escape(n.title),
                sensors=len(n),
                charts=len(n.getCharts()),
                start=formatTime(n.timegrid.start),
                stop=formatTime(n.timegrid.stop),
                step=n.timegrid.step,
                timezone=n.timegrid.timezone,
            ) + formatMetaData(n)
        elif t == "S":
            txt = sensorInfo.substitute(
                name=n.name,
                path="/".join(n.path.split("/")[:-1]),
                title=escape(n.title),
                start=formatTime(n.timegrid.start),
                stop=formatTime(n.timegrid.stop),
                step=n.timegrid.step,
                length=n.datalen(),
                timezone=n.timegrid.timezone,
            ) + formatMetaData(n)
        elif t == "C":
            txt = chartInfo.substitute(name=n.name, path=n.sensorgroup.path)
        self.textBrowser.setText(txt)
        msg = ": ".join(str(self.model.itemFromIndex(mi).data().toString()).split("|")[1:])
        self.statusBar.showMessage(msg, 5000)

    def searchItem(self):
        """execute the search and highlight the (next) result"""
        txt = str(self.searchInput.text())
        if txt != self.searchText:
            self.searchText = txt
            tmp = self.model.findItems(
                txt, Qt.MatchFixedString | Qt.MatchContains | Qt.MatchWildcard | Qt.MatchRecursive
            )
            self.searchList = [i.index() for i in tmp]
        if self.searchList:
            mi = self.searchList.pop()
            self.treeView.setCurrentIndex(mi)
            self.treeView.expand(mi)
            self.treeView.scrollTo(mi)
        else:
            QMessageBox.information(
                self,
                QCoreApplication.translate("DataStorageBrowser", "No (more) matches!"),
                QCoreApplication.translate(
                    "DataStorageBrowser", "No (more) matches found! Change you search text and try again!"
                ),
            )
            self.searchText = ""

    def expandCollapseAll(self):
        if self.collExpand():
            self.treeView.collapseAll()
        else:
            self.treeView.expandAll()

    def itemAction(self, mi):
        """default action (on doubleclick) for item at model index mi"""
        t, n = self.model.dsNode(mi)
        if t == "S":
            if qwtPlotWindowActive():
                self.addToQwtPlot(n)
            else:
                self.showQwtPlot(n)
        elif t == "C":
            self.showChart(n)

    def showContextMenu(self, pos):
        """show context menu for item at pos"""
        mi = self.treeView.indexAt(pos)
        t, n = self.model.dsNode(mi)
        self.selectedNode = n
        self.selectedMI = mi
        m = QMenu()
        if t == "R":
            m.addAction(QCoreApplication.translate("DataStorageBrowser", "Close"), self.closeDatabase)
            m.addAction(QCoreApplication.translate("DataStorageBrowser", "Reload"), self.reloadDatabase)
        elif t == "P":
            m.addAction(QCoreApplication.translate("DataStorageBrowser", "New sensorgroup"), self.newSensorGroup)
        elif t == "G":
            nCharts = len(n.getCharts())
            if nCharts > 0:
                txt = str(QCoreApplication.translate("DataStorageBrowser", "Show all charts (%d)")) % nCharts
                m.addAction(txt, self.showAllCharts)
                m.addAction(
                    QCoreApplication.translate("DataStorageBrowser", "Save all charts as images"),
                    self.saveAllChartImages,
                )
            m.addAction(QCoreApplication.translate("DataStorageBrowser", "Add chart"), self.newChart)
            m.addAction(QCoreApplication.translate("DataStorageBrowser", "Add/update data"), self.importFiles)
            m.addAction(QCoreApplication.translate("DataStorageBrowser", "Export data"), self.exportSensors)
        elif t == "S":
            m.addAction(QCoreApplication.translate("DataStorageBrowser", "New plot (Qwt)"), self.showQwtPlot)
            if qwtPlotWindowActive():
                m.addAction(QCoreApplication.translate("DataStorageBrowser", "Add to plot (Qwt)"), self.addToQwtPlot)
        elif t == "C":
            m.addAction(QCoreApplication.translate("DataStorageBrowser", "Show"), self.showChart)
            m.addAction(QCoreApplication.translate("DataStorageBrowser", "Delete"), self.deleteItem)
        if t in "RPGS":
            m.addSeparator()
            m.addAction(QCoreApplication.translate("DataStorageBrowser", "Edit metadata"), self.editMetadata)
        a = m.exec_(self.treeView.mapToGlobal(pos))

    def newSensorGroup(self, mi=None):
        if mi is None:
            mi = self.selectedMI
        newSensorGroup(self.model, mi)

    def showChart(self, ch=None):
        if ch is None:
            ch = self.selectedNode
        showChartWindow(ch, maximized=showChartMaximized)

    def importFiles(self, mi=None):
        if mi is None:
            mi = self.selectedMI
        importFiles(self.model, mi)

    def showAllCharts(self, sg=None):
        if sg is None:
            sg = self.selectedNode
        showAllChartWindows(sg, maximized=showChartMaximized)

    def saveAllChartImages(self, sg=None):
        if sg is None:
            sg = self.selectedNode
        saveAllChartImages(sg)

    def exportSensors(self, sg=None):
        if sg is None:
            sg = self.selectedNode
        exportSensors(sg)

    def showQwtPlot(self, se=None):
        if se is None:
            se = self.selectedNode
        showQwtPlotWindow(se, maximized=showChartMaximized)

    def addToQwtPlot(self, se=None):
        if se is None:
            se = self.selectedNode
        addToQwtPlotWindow(se)

    def editMetadata(self, node=None):
        if node is None:
            node = self.selectedNode
        editMetadata(node)

    def closeDatabase(self, mi=None):
        if mi is None:
            mi = self.selectedMI
        self.model.closeDatabase(mi)

    def reloadDatabase(self, mi=None):
        if mi is None:
            mi = self.selectedMI
        dbPath = self.model.dsFolder(mi)
        self.model.closeDatabase(mi)
        self.loadDatabase(dbPath)

    def newChart(self, mi=None):
        """add a chart to sensorgroup at mi using the wizard"""
        if mi is None:
            mi = self.selectedMI
        showNewChartWizard(self.model, mi, self)

    def deleteItem(self, mi=None):
        """delete the item at mi"""
        if mi is None:
            mi = self.selectedMI
        self.model.deleteItem(mi)
Esempio n. 24
0
class WellPlotMPL(QtCore.QObject):
    def __init__(self, logs, well, logSet=None, parent=None):
        super(WellPlotMPL, self).__init__(parent)

        self._well = well
        self._logSet = logSet
        self._logs = logs
        self.plots = []
        self.canvas = None
        self.depthPlot = None
        self.headerPlot = None
        centralWidget = centraltabwidget.CentralTabWidget()
        #id(self) returns the 'hash' of this object
        self.uid = (centralWidget.count(), id(self))
        self.wellPlotSignals = WellPlotSignals()

        self.setupUI()
        self.createTabView()
        self.connectSlots()
        self.plotMultiLogs()
        self.setSplitterStretch()
        self.createToolWidget()

    def setupUI(self):
        self.mainWidget = WellPlotWidget()
        vBox = QtGui.QVBoxLayout()
        self.mainWidget.setLayout(vBox)

        self.headerWidget = QWidget()
        self.headerLayout = QtGui.QHBoxLayout()
        self.headerWidget.setLayout(self.headerLayout)

        self.dataWidget = QWidget()
        self.dataLayout = QtGui.QHBoxLayout()
        self.dataWidget.setLayout(self.dataLayout)

        #if don't set a minimum, get matplotlib error when is very small
        self.dataWidget.setMinimumHeight(self.getMinimumVerticalHeight())

        self.splitter = QSplitter(QtCore.Qt.Vertical)

        self.headerScrollArea = QScrollArea()
        self.headerScrollArea.setVerticalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        self.headerScrollArea.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        self.headerScrollArea.setWidgetResizable(False)
        self.headerScrollArea.setWidget(self.headerWidget)

        self.scrollArea = QScrollArea()
        self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.scrollArea.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        self.scrollArea.setWidgetResizable(False)
        self.scrollArea.setWidget(self.dataWidget)
        #see http://stackoverflow.com/questions/29583927/pyqt-qscrollarea-within-qscrollarea/29584939#29584939
        self.scrollArea.horizontalScrollBar().valueChanged.connect(
            self.headerScrollArea.horizontalScrollBar().setValue)

        self.splitter.addWidget(self.headerScrollArea)
        self.splitter.addWidget(self.scrollArea)
        self.splitter.setStretchFactor(1, 10)

        vBox.addWidget(self.splitter)

    def getMinimumVerticalHeight(self):
        screenRect = QtGui.QDesktopWidget().screenGeometry()
        #need to set a minimum size otherwise get matplotlib error when rezizing to too small
        twentythOfScreen = int(round(screenRect.width() / 20))
        return twentythOfScreen

    def plotMultiLogs(self):
        logPlotModelAccess = WellPlotModelAccess()
        logPlotData = logPlotModelAccess.createWellPlotData(self._logs)
        self.createCanvas(logPlotData)
        self.plotHeaderFields(logPlotData)

    def createCanvas(self, logPlotData):
        logger.debug(">>createCanvas()")
        #test
        for subPlotData in logPlotData.sub_plots:
            logger.debug(
                "--createCanvas() plot_index:{0} track_width:{1} track_gap:{2}"
                .format(subPlotData.plot_index, subPlotData.track_width,
                        subPlotData.track_gap))
            for log in subPlotData._logs:
                logger.debug("--createCanvas id:{0}, name:{1}".format(
                    log.id, log.name))
        #end test
        if len(logPlotData.sub_plots) > 0:
            WidgetUtils.removeWidgets(self.dataLayout)

            #test
            #time.sleep(1) # delays for 1 second
            #end test

            #There may be a better way to link plots with the toolbar
            self.mainWidget.setLogPlotData(logPlotData)

            self.depthPlot = DepthAxis(logPlotData, self.dataWidget)
            self.dataLayout.addWidget(self.depthPlot)

            self.canvas = MultiLogCanvas(logPlotData, self.dataWidget)
            self.canvas.setAutoFillBackground(True)
            self.dataLayout.addWidget(self.canvas)

            spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding,
                                           QtGui.QSizePolicy.Minimum)
            self.dataLayout.addItem(spacerItem)
        else:
            logger.error("--plotMultiLogs() Error: no logs to plot")
            if AppSettings.isDebugMode:
                raise ValueError

    def plotHeaderFields(self, logPlotData):
        logger.debug(">>plotMultiLogs()")
        WidgetUtils.removeWidgets(self.headerLayout)
        self.headerPlot = HeaderPlotMPL(depthPlot=self.depthPlot,
                                        mainPlot=self.canvas,
                                        logPlotData=logPlotData)
        self.headerLayout.addWidget(self.headerPlot)

    def setSplitterStretch(self):
        #Minimum size is required for the QScrollArea.setWidgetResizable(False) setting'''
        headerW = self.headerPlot.width()
        headerH = self.headerPlot.height()
        self.headerWidget.setMinimumSize(headerW, headerH)

        #test
        (totalW, dataH) = MplUtils.calcFigCanvasWidthHeight(self.canvas.figure)
        #end test
        dWidth, dHeight = self.canvas.figure.canvas.get_width_height()

        self.dataWidget.setMinimumSize(dWidth, dHeight)

    def connectSlots(self):
        logger.debug(">>connectSlots")
        self.wellPlotSignals.logPlotSettingsModified.connect(self.replotLogs)

    @pyqtSlot(WellPlotData)
    def replotLogs(self, logPlotData):
        logger.debug(">>replotLogs len(logPlotData.sub_plots): " +
                     str(len(logPlotData.sub_plots)))
        #check uid's before accessing them, where uid is a (number widgets in central widget, id) tuple
        logger.debug(
            "--replotLogs() len(self.uid):{0}, len(logPlotData.uid):{1}".
            format(len(self.uid), len(logPlotData.uid)))
        if (len(self.uid) == 2) and (len(logPlotData.uid) == 2):
            #ensure this object is associated with the plot object
            if self.uid[0] == logPlotData.uid[0] and self.uid[
                    1] == logPlotData.uid[1]:
                logger.debug("--replotLogs() match found uid: " +
                             str(self.uid[0]))

                self.createCanvas(logPlotData)
                self.plotHeaderFields(logPlotData)

    def spacePlots(self, bottomLayout):
        rightSpacer = QtGui.QWidget()
        rightSpacer.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                  QtGui.QSizePolicy.Expanding)
        #topLayout.addWidget(rightSpacer)
        bottomLayout.addWidget(rightSpacer)
        #self.topWidget.setLayout(topLayout)
        self.dataWidget.setLayout(bottomLayout)

    def createTabView(self):
        centralWidget = centraltabwidget.CentralTabWidget()
        self.mainWidget.setData(self.uid)
        #centralWidget.addTab(self.scrollArea, "Well plot "+str(self.uid[0]))
        centralWidget.addTab(self.mainWidget, "Well plot " + str(self.uid[0]))

    def createToolWidget(self):
        if len(self._logs) > 0:
            toolbar = logsettingstoolbar.LogSettingsToolbar()
            toolbar.setData(self._well, self._logSet, self.canvas,
                            self.depthPlot, self.headerPlot)
            toolbar.emitShowToolbarSignal()
            logger.debug("<<createToolWidget() toolbar created")
Esempio n. 25
0
    def createWidgets(self):
        """
        QtWidgets creation

         ___________   _________________
        |           | |                 |
        |           | |                 |
        |           | |                 |
        | TestsItem | | TextualLogView  |
        |           | |                 |
        |           | |                 |
        |___________| |_________________|
        """
        layout = QHBoxLayout()

        self.logsItem = TestsView.TestsView(parent=self, local=self.local)

        self.resumeView = ResumeView.TextualView(parent=self)
        if QtHelper.str2bool(
                Settings.instance().readValue(key='TestRun/hide-resume-view')):
            self.hideResumeView()

        self.graphView = GraphView.FlowChartView(parent=self)
        self.logsView = TextualView.TextualView2(parent=self)
        self.hexLogsView = DetailedView.DetailedView(parent=self)

        self.displayTab = QTabWidget()

        hSplitter = QSplitter(self)
        hSplitter.setOrientation(Qt.Vertical)

        hSplitter.addWidget(self.resumeView)
        hSplitter.addWidget(self.logsView)
        hSplitter.addWidget(self.hexLogsView)

        self.displayTab.addTab(hSplitter, self.tr('Events'))
        self.displayTab.addTab(self.graphView, self.tr('Diagram'))

        defaultTab = Settings.instance().readValue(
            key='TestRun/default-tab-run')
        self.displayTab.setCurrentIndex(int(defaultTab))

        self.currentEdit = QLineEdit()
        self.currentEdit.setReadOnly(True)
        self.currentEdit.setStyleSheet(
            "QLineEdit { background-color : #F0F0F0; color: grey; }")

        leftFrame = QFrame()
        leftLayout = QVBoxLayout()
        leftLayout.setContentsMargins(0, 0, 0, 0)
        leftFrame.setLayout(leftLayout)

        leftLayout.addWidget(self.currentEdit)
        leftLayout.addWidget(self.displayTab)

        v_splitter = QSplitter(self)
        v_splitter.addWidget(self.logsItem)
        v_splitter.addWidget(leftFrame)
        v_splitter.setStretchFactor(1, 1)

        layout.addWidget(v_splitter)

        self.setLayout(layout)
Esempio n. 26
0
class EntryView(BaseView):
    def _setup(self):
        self._setupUi()
        self.etable = EntryTable(self.model.etable, view=self.tableView)
        self.efbar = EntryFilterBar(model=self.model.filter_bar, view=self.filterBar)
        self.bgraph = Chart(self.model.bargraph, view=self.barGraphView)
        self.lgraph = Chart(self.model.balgraph, view=self.lineGraphView)
        self._setupColumns() # Can only be done after the model has been connected
        
        self.reconciliationButton.clicked.connect(self.model.toggle_reconciliation_mode)
    
    def _setupUi(self):
        self.resize(483, 423)
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setSpacing(0)
        self.verticalLayout.setMargin(0)
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setSpacing(0)
        self.filterBar = RadioBox(self)
        sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.filterBar.sizePolicy().hasHeightForWidth())
        self.filterBar.setSizePolicy(sizePolicy)
        self.horizontalLayout.addWidget(self.filterBar)
        self.horizontalLayout.addItem(horizontalSpacer())
        self.reconciliationButton = QPushButton(tr("Reconciliation"))
        self.reconciliationButton.setCheckable(True)
        self.horizontalLayout.addWidget(self.reconciliationButton)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.splitterView = QSplitter()
        self.splitterView.setOrientation(Qt.Vertical)
        self.splitterView.setChildrenCollapsible(False)
        self.tableView = TableView(self)
        self.tableView.setAcceptDrops(True)
        self.tableView.setEditTriggers(QAbstractItemView.DoubleClicked|QAbstractItemView.EditKeyPressed)
        self.tableView.setDragEnabled(True)
        self.tableView.setDragDropMode(QAbstractItemView.InternalMove)
        self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tableView.setSortingEnabled(True)
        self.tableView.horizontalHeader().setHighlightSections(False)
        self.tableView.horizontalHeader().setMinimumSectionSize(18)
        self.tableView.verticalHeader().setVisible(False)
        self.tableView.verticalHeader().setDefaultSectionSize(18)
        self.splitterView.addWidget(self.tableView)
        self.graphView = QStackedWidget(self)
        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.graphView.sizePolicy().hasHeightForWidth())
        self.graphView.setSizePolicy(sizePolicy)
        self.graphView.setMinimumSize(0, 200)
        self.lineGraphView = LineGraphView()
        self.graphView.addWidget(self.lineGraphView)
        self.barGraphView = BarGraphView()
        self.graphView.addWidget(self.barGraphView)
        self.splitterView.addWidget(self.graphView)
        self.graphView.setCurrentIndex(1)
        self.splitterView.setStretchFactor(0, 1)
        self.splitterView.setStretchFactor(1, 0)
        self.verticalLayout.addWidget(self.splitterView)
    
    def _setupColumns(self):
        h = self.tableView.horizontalHeader()
        h.setMovable(True) # column drag & drop reorder
    
    #--- QWidget override
    def setFocus(self):
        self.etable.view.setFocus()
    
    #--- Public
    def fitViewsForPrint(self, viewPrinter):
        hidden = self.model.mainwindow.hidden_areas
        viewPrinter.fitTable(self.etable)
        if PaneArea.BottomGraph not in hidden:
            viewPrinter.fit(self.graphView.currentWidget(), 300, 150, expandH=True, expandV=True)
    
    def restoreSubviewsSize(self):
        graphHeight = self.model.graph_height_to_restore
        if graphHeight:
            splitterHeight = self.splitterView.height()
            sizes = [splitterHeight-graphHeight, graphHeight]
            self.splitterView.setSizes(sizes)
    
    #--- model --> view
    def refresh_reconciliation_button(self):
        if self.model.can_toggle_reconciliation_mode:
            self.reconciliationButton.setEnabled(True)
            self.reconciliationButton.setChecked(self.model.reconciliation_mode)
        else:
            self.reconciliationButton.setEnabled(False)
            self.reconciliationButton.setChecked(False)
    
    def show_bar_graph(self):
        self.graphView.setCurrentIndex(1)
    
    def show_line_graph(self):
        self.graphView.setCurrentIndex(0)
    
    def update_visibility(self):
        hidden = self.model.mainwindow.hidden_areas
        self.graphView.setHidden(PaneArea.BottomGraph in hidden)
Esempio n. 27
0
File: help.py Progetto: kzwkt/dff
class Help(QDockWidget):
    def __init__(self, parent=None, path=None):
        QDockWidget.__init__(self, parent)
        self.name = self.tr("Help")
        self.setFloating(False)
        self.setFeatures(QDockWidget.NoDockWidgetFeatures)

        self.__mainWidget = QSplitter(Qt.Horizontal)
        self.__uname = QWidget()

        mainWidgetLayout = QVBoxLayout(self.__uname)
        mainWidgetLayout.setContentsMargins(0, 0, 0, 0)

        # create helper + search engine
        self.__helper = QHelpEngine(path, self)

        if not self.__helper.setupData() is True:
            dialog = QMessageBox()

            msg = QString(
                self.tr("An error occurred while setting help engine up :\n"))
            msg += (self.__helper.error() + "\n")
            msg += self.tr(
                "It might mean that the format of your help file is not correct.\n"
            )
            msg += self.tr(
                "You can check on-line help at http://wiki.digital-forensic.org"
            )

            dialog.setText(msg)
            dialog.setIcon(QMessageBox.Warning)
            dialog.setWindowTitle(self.tr("Error while loading help"))
            dialog.exec_()
            return

        self.__toc = self.__helper.contentWidget()
        self.__helpBrowser = HelpBrowser(self.__helper)

        # build main widget
        self.__toolbar = QWidget()
        self.__toolbarLayout = QHBoxLayout(self.__toolbar)
        home = QPushButton(QIcon(":home.png"), "")
        previous = QPushButton(QIcon(":previous.png"), "")
        next = QPushButton(QIcon(":next.png"), "")

        # building toolbar
        self.__toolbarLayout.addWidget(home)
        self.__toolbarLayout.addWidget(previous)
        self.__toolbarLayout.addWidget(next)
        self.__toolbarLayout.setContentsMargins(0, 0, 0, 0)
        mainWidgetLayout.addWidget(self.__toolbar)
        mainWidgetLayout.addWidget(self.__helpBrowser)
        self.__mainWidget.insertWidget(0, self.__toc)
        self.__mainWidget.insertWidget(1, self.__uname)
        self.__mainWidget.setStretchFactor(1, 1)
        self.setWidget(self.__mainWidget)

        #connecting `previous`, `home` and `next` buttons
        self.connect(next, SIGNAL("clicked(bool)"),
                     self.__helpBrowser.nextPage)
        self.connect(previous, SIGNAL("clicked(bool)"),
                     self.__helpBrowser.prevPage)
        self.connect(home, SIGNAL("clicked(bool)"), self.__helpBrowser.goHome)
        self.connect(self.__helper.contentWidget(),
                     SIGNAL("linkActivated(const QUrl &)"),
                     self.__helpBrowser.setSource)
Esempio n. 28
0
class Filter(Ui_filterAdd, QDialog):
    def __init__(self, filtertable, fname=None, query=None):
        super(QDialog, self).__init__(filtertable)
        self.filtertable = filtertable
        self.setupUi(self)
        self.editable = False
        self.defaultquery = None
        self.fname = None
        sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        self.setSizePolicy(sizePolicy)
        self.requestLayout.setSpacing(6)
        self.requestLayout.setSizeConstraint(QLayout.SetMinimumSize)
        self.requestLayout.setMargin(0)
        self.__splitter = QSplitter(Qt.Vertical)
        self.__splitter.setHandleWidth(12)
        self.requestLayout.addWidget(self.__splitter)
        self.__query = QTextEdit()
        self.__query.setReadOnly(True)
        if (fname == None) and (query == None):
            self.editable = True
            self.filterRequest = FilterRequests(self)
            self.connect(self.filterRequest, SIGNAL("queryUpdated"),
                         self.updateQuery)
            self.__splitter.addWidget(self.filterRequest)
            self.__splitter.addWidget(self.__query)
            self.__splitter.setStretchFactor(0, 80)
            self.__splitter.setStretchFactor(1, 20)
        else:
            self.defaultquery = query
            self.fname = fname

    def updateQuery(self):
        query = self.buildRequest()
        self.__query.setText(query)

    def reject(self):
        QDialog.reject(self)

    def accept(self):
        if not self.name().isEmpty():
            QDialog.accept(self)
        else:
            box = QMessageBox(QMessageBox.Critical, self.tr("Error"), self.tr("Please, specify a query name"), \
                                QMessageBox.NoButton, self)
            box.exec_()

    def isEditable(self):
        return self.editable

    def name(self):
        if self.editable:
            return self.filterName.text()
        else:
            return self.fname

    def buildRequest(self):
        if self.editable:
            row = 0
            res = "("
            while row < self.filterRequest.rowCount():
                if row > 0:
                    conj = self.filterRequest.cellWidget(row, 0)
                    res += " " + CONJONCTIONS[
                        conj.conjunctionCombo.currentIndex()] + " "
                widget = self.filterRequest.cellWidget(row, 2)
                res += widget.request()
                row += 1
            res += ")"
            return res
        else:
            return self.defaultquery
Esempio n. 29
0
class NPhotoMainWindow(QMainWindow):
    rootAlbum = None
    currentPage = 0
    
    def __init__(self, parent=None):
        super(NPhotoMainWindow, self).__init__(parent)

        self.image = None 
        self.status = self.statusBar()
        self.status.setSizeGripEnabled(False)

        fileMenu = self.menuBar().addMenu("&File")
        fileEditAction = createAction(self, "&Edit", self.doEdit, "Ctrl-E", "fileedit", "Edit photo details")
        fileDeleteAction = createAction(self, "&Delete", self.doDelete, "Ctrl-D", "filedelete", "Delete selected file(s)")
        fileImportAction = createAction(self, "&Import", self.doImport, "Ctrl-I", "fileimport", "Import photos into your library")
        fileRescanLibraryAction = createAction(self, "&Rescan", self.doRescan, "Ctrl-R", "filerescan", "Rescan library folder and update sidecar files, and thumbnails")
        fileBackupAction = createAction(self, "&Backup", self.doBackup, "Ctrl-B", "filebkup", "Backup your library")
        fileSettingsAction = createAction(self, "&Settings", self.doSettings, "Ctrl-S", "filesettings", "Settings")
        fileQuitAction = createAction(self, "&Quit", self.close, "Ctrl+Q", "filequit", "Close the application")

        helpMenu = self.menuBar().addMenu("&Help")
        helpAboutAction = createAction(self, "&About", self.doAbout, None, "helpabout", "About nPhoto")
        
        addActions(fileMenu, (fileEditAction, fileDeleteAction, None, fileImportAction, fileRescanLibraryAction,
                              fileBackupAction, fileSettingsAction, None, fileQuitAction))
        addActions(helpMenu, (helpAboutAction,))
    
        size = getSettingQVar("MainWindow/Size", QSize(600,500)).toSize()
        self.resize(size)
        position = getSettingQVar("MainWindow/Position", QPoint(0,0)).toPoint()
        self.move(position)
        self.restoreState(getSettingQVar("MainWindow/State").toByteArray())
        self.setWindowTitle("nPhoto")

        self.controlFrame = QFrame()
        self.controlLayout = QBoxLayout(QBoxLayout.TopToBottom)

        #TODO Make this a combo box that populates the tree by date or by folder
        self.viewByCombo = QLabel("PLACEHOLDER")
        
        self.tree = QTreeWidget()

        self.tree.setColumnCount(1)
        self.tree.setHeaderLabels(["Album"])
        self.tree.setItemsExpandable(True)

        self.connect(self.tree, SIGNAL("itemSelectionChanged()"), self.treeSelection)

        self.controlLayout.addWidget(self.viewByCombo)
        self.controlLayout.addWidget(self.tree)

        self.controlFrame.setLayout(self.controlLayout)

        self.browserFrame = QFrame()

        self.browserGrid = QGridLayout()

        self.imageLabels = []
        for row in range(0,BROWSER_GRID_HEIGHT):
            self.imageLabels.append([])
            for col in range(0,BROWSER_GRID_WIDTH):
                self.imageLabels[row].append(QLabel())
                self.imageLabels[row][col].setBackgroundRole(QPalette.Base)
                self.imageLabels[row][col].setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
                self.imageLabels[row][col].setScaledContents = True
                self.imageLabels[row][col].setAlignment(Qt.AlignCenter)
                self.imageLabels[row][col].setStyleSheet("border:2px solid #000")

                dbl = functools.partial(self.imgDoubleClick, row, col)
                click = functools.partial(self.imgMouseRelease, row, col)
                
                self.imageLabels[row][col].mouseDoubleClickEvent = dbl
                self.imageLabels[row][col].mouseReleaseEvent = click
                self.browserGrid.addWidget(self.imageLabels[row][col],row,col)

        self.prevPage = QPushButton("Prev")
        self.pageInfoLabel = QLabel("Page 0 of 0")
        self.pageInfoLabel.setAlignment(Qt.AlignCenter)
        self.nextPage = QPushButton("Next")

        self.prevPage.clicked.connect(self.goPreviousPage)
        self.nextPage.clicked.connect(self.goNextPage)
        
        self.browserGrid.addWidget(self.prevPage, row+1, 0)
        self.browserGrid.addWidget(self.pageInfoLabel, row+1, 1)
        self.browserGrid.addWidget(self.nextPage, row+1, 2)

        self.browserFrame.setLayout(self.browserGrid)

        self.mainSplitter = QSplitter(Qt.Horizontal)
        self.mainSplitter.addWidget(self.controlFrame)
        self.mainSplitter.addWidget(self.browserFrame)
        self.mainSplitter.setStretchFactor(1,4)
        
        self.setCentralWidget(self.mainSplitter)

        self.mainSplitter.restoreState(getSettingQVar("MainWindow/Splitter").toByteArray())

        if getSettingStr("Paths/Library") not in (None, ''):
            QTimer.singleShot(0, self.loadLibrary)
        else:
            self.status.showMessage("No Library Path in settings", 10000)

    def getPhotoByBrowserLocation(self, row, col):
        idx = ((self.currentPage - 1) * BROWSER_THUMBS_PER_PAGE) + (row * BROWSER_GRID_WIDTH) + col
        if idx < len(self.currentAlbum.photos):
            return self.currentAlbum.photos[idx]
        else:
            return None

    def imgDoubleClick(self, row, col, event):

        if event.button() == Qt.LeftButton:
            if event.modifiers() & Qt.ControlModifier or event.modifiers() & Qt.AltModifier \
                    or event.modifiers() & Qt.ShiftModifier:
                pass
            else:
                curr = self.getPhotoByBrowserLocation(row,col)
                if curr:
                    self.currentSelection = [curr,]
                    self.highlightSelected()
                    self.doEdit()        

    def imgMouseRelease(self, row, col, event):
        if event.button() == Qt.LeftButton:
            if event.modifiers() & Qt.ControlModifier or event.modifiers() & Qt.AltModifier \
                or event.modifiers() & Qt.ShiftModifier:
                pass
            else:
                curr = self.getPhotoByBrowserLocation(row,col)
                if curr:
                    if not hasattr(self, "currentSelection"):
                        self.currentSelection = []

                    if curr in self.currentSelection:
                        self.currentSelection.remove(curr)
                    else:
                        self.currentSelection.append(curr)

        self.highlightSelected()

    def highlightSelected(self):
        if hasattr(self, "currentSelection"):
            for x in range(0, BROWSER_GRID_HEIGHT):
                for y in range(0, BROWSER_GRID_WIDTH):
                    ph = self.getPhotoByBrowserLocation(x,y)
                    if ph:
                        if ph in self.currentSelection:
                            self.imageLabels[x][y].setStyleSheet("border:2px solid #FFF")
                        else:
                            self.imageLabels[x][y].setStyleSheet("border:2px solid #000")



    def regenAlbumThumbnails(self, album):
        for al in album.albums:
            self.regenAlbumThumbnails(al)

        for ph in album.photos:
            createThumbnail(ph.path, True)
        
    def doRescan(self):
        #TODO Rebuild sidecar files!

        self.regenAlbumThumbnails(self.rootAlbum)
        self.reloadLibrary()

        

    def treeSelection(self):
        curr = self.tree.currentItem()
        path = curr.data(0,0).toString()
        tmp = curr
        while tmp.parent() is not None:
            tmp = tmp.parent()
            path = tmp.data(0,0).toString() + "." + path

        album = self.getAlbum(path)
        if hasattr(self, 'currentAlbum'):
            if self.currentAlbum != album:
                self.currentAlbum = album
        else:
            self.currentAlbum = album
        self.changeAlbums()

    def changeAlbums(self):
        if len(self.currentAlbum.photos) == 0:
            self.currentPage = 0
        else:
            self.currentPage = 1
        
        for row in range(0, BROWSER_GRID_HEIGHT):
            for col in range(0, BROWSER_GRID_WIDTH):
                if len(self.currentAlbum.photos)<= (row*BROWSER_GRID_WIDTH + col):
                    self.imageLabels[row][col].setPixmap(QPixmap())
                else:
                    self.imageLabels[row][col].setPixmap(loadQPixMap(self.image, self.currentAlbum.photos[
                            (BROWSER_THUMBS_PER_PAGE * (self.currentPage - 1)) + row*BROWSER_GRID_WIDTH+col]
                                                                          .path, self.imageLabels[0][0].width(), self.imageLabels[0][0].height(), True))
                    self.imageLabels[row][col].adjustSize()

        self.updatePageInfo()

    def loadPageThumbs(self):
        for row in range(0, BROWSER_GRID_HEIGHT):
            for col in range(0, BROWSER_GRID_WIDTH):
                if len(self.currentAlbum.photos)<= (
                            (BROWSER_THUMBS_PER_PAGE * (self.currentPage - 1)) + row*BROWSER_GRID_WIDTH + col):
                    self.imageLabels[row][col].setPixmap(QPixmap())
                else:
                    self.imageLabels[row][col].setPixmap(loadQPixMap(self.image, self.currentAlbum.photos[
                            (BROWSER_THUMBS_PER_PAGE * (self.currentPage - 1)) + row*BROWSER_GRID_WIDTH+col]
                                                                          .path, self.imageLabels[0][0].width(), self.imageLabels[0][0].height(), True))
                    self.imageLabels[row][col].adjustSize()


    def goPreviousPage(self):
        if self.currentPage > 1:
            self.currentPage -= 1
            self.loadPageThumbs()
            self.updatePageInfo()

    def goNextPage(self):
        if self.currentPage < self.getMaxPage():
            self.currentPage += 1
            self.loadPageThumbs()
            self.updatePageInfo()

    def getMaxPage(self):
        totalPages = len(self.currentAlbum.photos) / BROWSER_THUMBS_PER_PAGE
        if (len(self.currentAlbum.photos) % BROWSER_THUMBS_PER_PAGE) != 0:
            totalPages += 1
        return totalPages
        

    def updatePageInfo(self):
        if self.currentPage == 0:
            self.pageInfoLabel.setText("Page 0 of 0")
        else:
            self.pageInfoLabel.setText("Page %d of %d" % (self.currentPage, self.getMaxPage()))
                                                   
    def getAlbum(self, path):
        nodes = path.split(".")
        if nodes[0] != 'Library':
            print "WTF?!?!?!"
        else:
            album = self.rootAlbum
            for albumName in nodes[1:]:
                album = album.albums[unicode(albumName)]

            return album
        
    def doBackup(self):
        libDir = getSettingStr("Paths/Library")
        bkupPaths = getSettingStr("Paths/Backup")
        
        if libDir in (None,  ''):
            QMessageBox.warning(self, "Backup Failed", "You need to specify a library directory in your settings")
            return
        if not os.path.exists(libDir) or os.path.isfile(libDir):
            QMessageBox.warning(self, "Backup Failed", "The library directory in your settings either doesn't exist, or its not a directory")
            return        
        
        if bkupPaths in (None,  ''):
            QMessageBox.warning(self, "Backup Failed",  "You need to specify at least one backup directory in your settings")
            return

        dt = datetime.date.today()
        bkupDirName = str(dt.year) + str(dt.month) + str(dt.day)

        for path in bkupPaths.split(","):
            if not os.path.exists(path.strip()) or os.path.isfile(path.strip()):
                QMessageBox.warning(self, "Backup Failed", "The backup directory <%s> in your settings either doesn't exist, or its not a directory" % (path))
                return
        
            if os.path.exists(path.strip() + os.sep + bkupDirName):
                QMessageBox.warning(self, "Backup Failed", "There is already a backup for today in a backup directory <%s>" % (path.strip()))
                return
        
        for path in bkupPaths.split(","):
            shutil.copytree(libDir, path.strip() + os.sep + bkupDirName)
        
        QMessageBox.information(self, "Backup", "Backup completed!")

    def doDelete(self):
        if hasattr(self, "currentSelection"):
            if len(self.currentSelection) > 0:
                msg = "Are you sure you want to delete the selected image?"
                if len(self.currentSelection) > 1:
                    msg = "Are you sure you want to delete the %s selected images?" % len(self.currentSelection)
                    
                if QMessageBox.warning(self, "Delete Image(s)", msg,
                                             QMessageBox.Yes|QMessageBox.No) == QMessageBox.Yes:
                    for ph in self.currentSelection:
                        msg = ph.delete()
                        if msg not in (None, ''):
                            QMessageBox.warning(self, "Error while deleting", msg)
                            break

                    self.reloadLibrary()
                    

    def reloadLibrary(self):
        self.currentSelection = []
        self.highlightSelected()
        
        currPage = self.currentPage

        self.loadLibrary()
        if currPage > self.getMaxPage():
            #Assumes you can't delete more than one page worth of photos at a time
            currPage = self.getMaxPage()

        self.currentPage = currPage
        self.loadPageThumbs()
        self.updatePageInfo()


    def doEdit(self):
        if hasattr(self, "currentSelection"):
            if len(self.currentSelection) == 1:
                ph = self.currentSelection[0]
                comment = ph.comment
                keywords = (" ".join(ph.keywords)).strip()
                dialog = EditPhotoDialog(self, ph.path, comment, keywords)
                if dialog.exec_():
                    ph.comment = unicode(dialog.commentEdit.text()).strip()
                    ph.keywords = unicode(dialog.keywordEdit.text()).strip().split(" ")
                    ph.save(ph.path)

    def doSettings(self):
        libPath = getSettingStr("Paths/Library", "")
        backupPaths = getSettingStr("Paths/Backup", "")
        fileExt = getSettingStr("FileExtensions", "jpg, CR2")
        fileExtOther = getSettingStr("FileExtensionsOther", "mov, avi")
        
        
        dialog = SettingsDialog(self, libPath, backupPaths, fileExt, fileExtOther)
        if dialog.exec_():
            saveSetting("Paths/Library", dialog.libPathEdit.text())
            saveSetting("Paths/Backup", dialog.backupPathsEdit.text())
            saveSetting("FileExtensions", dialog.fileExtensionEdit.text())
            saveSetting("FileExtensionsOther", dialog.fileExtensionOtherEdit.text())
            
            self.status.showMessage("Settings updated", 5000)
            

    def buildTree(self, parentNode, parentAlbum):
        for name in parentAlbum.albums:
            childNode = QTreeWidgetItem(parentNode, [name])
            childAlbum = parentAlbum.albums[name]
            if childAlbum.albums != None and len(childAlbum.albums) > 0:
                self.buildTree(childNode, childAlbum)

    def loadLibrary(self):
        self.status.showMessage("Loading Photo Library")

        self.rootAlbum = self.loadAlbum(getSettingStr("Paths/Library"), "Library")

        if self.rootAlbum == None:
            self.rootAlbum = Album(name="Library")

        self.refreshTree()
        
        self.status.showMessage("Library successfully loaded", 5000)

    def refreshTree(self):
        self.tree.clear()
        node = QTreeWidgetItem(self.tree, ["Library"])
        self.buildTree(node, self.rootAlbum)
        self.tree.setCurrentItem(node)

    def loadAlbum(self, path, title = None):
        album = Album()
        if title not in (None, ''):
            album.name = title
        else:
            album.name = path[path.rfind(os.sep)+1:]
            
        album.albums = {}
        album.photos = []
        album.path = path

        files = os.listdir(path)
        files.sort()

        tmpPhotos = []
        for fl in files:
            if not os.path.isfile(path + os.sep + fl):
                album.albums[fl] = self.loadAlbum(path + os.sep + fl)
            else:
                if self.isImageFile(path + os.sep + fl):
                    ph = None
                    if os.path.exists(path + os.sep + fl + ".sidecar"):
                        ph = Photo.load(path + os.sep + fl + ".sidecar")
                    else:
                        ph = Photo()
                        ph.comment = ""
                        ph.keywords = {}
                        ph.srcPath = None
                        ph.path = path + os.sep + fl
                        exif = loadExif(path + os.sep + fl, EXIF_TAGS)
                        ph.setExif(exif)
                        ph.save(path + os.sep + fl)

                    ph.path = path + os.sep + fl
                    tmpPhotos.append(ph)

        album.photos = sorted(tmpPhotos, key = lambda photo: photo.date)
        return album

    def doImport(self):
        libPath = getSettingStr("Paths/Library")
        fileExt = getSettingStr("FileExtensions")
        
        if libPath in (None,  ''):
            QMessageBox.warning(self, "Import Failed",  "You need to specify a library directory in your settings")
            return
        
        if not os.path.exists(libPath) or os.path.isfile(libPath):
            QMessageBox.warning(self, "Import Failed", "The library directory in your settings either doesn't exist, or its not a directory")
            return
            
        if not fileExt or fileExt in (None, ''):
            QMessageBox.warning(self, "Import Failed", "You need to specify file extensions to manage in your settings")
            return

        lastImport = getSettingStr("Paths/LastImport")

        importFrom = QFileDialog.getExistingDirectory(self, "Choose a Path to Import From", lastImport)
        
        if importFrom in (None,  ''):
            return
        
        if not os.path.exists(importFrom) or os.path.isfile(importFrom):
            QMessageBox.warning(self, "Import Failed", "The import directory either doesn't exist, or is not a directory")
            return

        if importFrom == libPath:
            QMessageBox.warning(self, "Import Failed", "Your import directory and library directory can not be the same")
            return

        imd = ImportMetadataDialog(self)

        if imd.exec_():
            album = imd.albumEdit.text()
            comments = imd.commentsEdit.text()
            keywords = imd.keywordsEdit.text()
            
            if album and album not in (None, ''):
                albumpath = album + os.sep
            else:
                album = None
                albumpath = ""
            
            if not keywords or keywords in (None, ''):
                keywords = ""

            if not comments or comments in (None, ''):
                comments = ""

            paths = self.buildFileList(importFrom)
            numTotal = len(paths)
            
            nonDupes = self.removeDuplicates(paths, importFrom, albumpath)
            numDuplicates = numTotal - len(nonDupes)
            
            if QMessageBox.question(self, "Import", "Out of %d files found, %d look to be duplicates. Continue with import?"
                                    % (numTotal,  numDuplicates), QMessageBox.Yes|QMessageBox.No) == QMessageBox.Yes:
                
                saveSetting("Paths/LastImport", importFrom)
                
                for path in nonDupes:
                    dest = self.buildLibPath(importFrom, path, albumpath)
                    copyFileIncludingDirectories(path, dest)
                    # TODO Handle copy failure exceptions!
                    
                    if not os.path.exists(dest):
                        QMessageBox.warming(self, "Import Failed", "The file <%s> was not imported properly, aborting import" % (path))
                        return
                    if self.isImageFile(path):
                        exif = loadExif(unicode(path), EXIF_TAGS)
                        ph = Photo()
                        ph.path = dest
                        ph.srcPath = path
                        ph.comment = comments
                        ph.keywords = keywords
                        ph.setExif(exif)
                        ph.save(dest)

                        #Create Thumbnail
                        createThumbnail(unicode(ph.path))
                        
                QMessageBox.information(self, "Import", "Import completed")

                self.loadLibrary()
            
    def buildLibPath(self, importFrom, path, albumpath):
        relPath = path[len(importFrom):]
        libPath = getSettingStr("Paths/Library") + os.sep + albumpath + relPath
        
        return libPath

        
    def isImageFile(self, filepath):
        extensionList = unicode(getSettingStr("FileExtensions")).split(",")
        for extension in extensionList:
            if unicode(filepath).upper().endswith(unicode(extension).upper()):
                return True
        return False

    def isOtherManagedFile(self, filepath):
        #TODO Implement list of other files to import into lib folders and to backup
        extensionList = unicode(getSettingStr("FileExtensionsOther")).split(",")
        for extension in extensionList:
            if unicode(filepath).upper().endswith(unicode(extension).upper()):
                return True
        return False
    

        
    def removeDuplicates(self, paths, importFrom, albumpath):
        nonDupes = []
        
        for path in paths:
            libPath = self.buildLibPath(importFrom, path, albumpath)
            if not os.path.exists(libPath):
                nonDupes.append(path)
        
        return nonDupes

    def buildFileList(self, importFrom):
        #TODO Can probably be done with Glob or whatever it is?
        paths = []
        for f in os.listdir(importFrom):
            fullpath = importFrom + os.sep + f
            
            if not os.path.isfile(fullpath):
                paths.extend(self.buildFileList(fullpath))
            else:
                if self.isImageFile(fullpath):
                    paths.append(fullpath)
                elif self.isOtherManagedFile(fullpath):
                    paths.append(fullpath)
                    
        return paths

    def closeEvent(self, event):
        saveSetting("MainWindow/Size", self.size())
        saveSetting("MainWindow/Position", self.pos())
        saveSetting("MainWindow/State", self.saveState())
        saveSetting("MainWindow/Splitter", self.mainSplitter.saveState())

    def doAbout(self):
        QMessageBox.about(self, "About nPhoto",
                "<p>nPhoto allows simple reviewing, commenting, and keywording of images, useful for running"
                                " on a netbook while travelling, to then import into programs such as Lightroom"
                                " on return from your holiday</p>")
Esempio n. 30
0
class EventLogViewer(QWidget):
    def __init__(self, node=None, chunks=None, parent=None):
        super(EventLogViewer, self).__init__(parent)

        self.display_mode = 0
        #  self.chunks = chunks
        self.node = node

        self.evtx_parser = EvtxXml(chunks, self.node)

        self.level = [
            ':/audit_success', ':/audit_failure', ':/error', ':/warning',
            ':/info', ':/chat.png'
        ]

        self.txt = [
            'Audit success', 'Audit failure', 'Error', 'Warning',
            'Information', 'Comment'
        ]

        self.disp = None
        self.current_row = 0
        self.widget = None

        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setMargin(3)
        self.splitter = QSplitter(self)
        self.splitter.setOrientation(Qt.Horizontal)

        #self.evtx_table_view = QTableWidget(self.splitter)
        self.evtx_table_view = EvtxTableView(self.splitter, self)
        self.admin_pannel = EvtxAdminPannel(self.splitter, chunks or [])

        self.verticalLayout.addWidget(self.splitter)
        self.splitter.setStretchFactor(0, 2)

        if PYQT_VERSION_STR >= "4.5.0":
            self.evtx_table_view.cellDoubleClicked.connect(self.dispEvent)
            self.admin_pannel.admin_events.clicked.connect(
                self.dispAdminEvents)
            self.admin_pannel.choose_event_type.activated.connect(
                self.dispEventType)

            self.admin_pannel.cb.activated.connect(self.dispIdL)
            self.admin_pannel.cbs.activated.connect(self.dispSourceL)

            self.admin_pannel.search_id.clicked.connect(self.dispId)
            self.admin_pannel.search_source.clicked.connect(self.dispSource)
            self.admin_pannel.search_date.clicked.connect(self.dispDate)
        else:
            QObject.connect(self.evtx_table_view,
                            SIGNAL("cellDoubleClicked(int, int)"),
                            self.dispEvent)
            QObject.connect(self.admin_pannel.admin_events,
                            SIGNAL("clicked(bool)"), self.dispAdminEvents)
            QObject.connect(self.admin_pannel.search_id,
                            SIGNAL("clicked(bool)"), self.dispId)
            QObject.connect(self.admin_pannel.search_source,
                            SIGNAL("clicked(bool)"), self.dispSource)
            QObject.connect(self.admin_pannel.search_date,
                            SIGNAL("clicked(bool)"), self.dispSource)
            QObject.connect(self.admin_pannel.choose_event_type,
                            SIGNAL("currentIndexChanged(int)"),
                            self.dispEventType)

    def addEvents(self, events):
        self.evtx_table_view.addEvents(events)

    def display(self, chunks, node=None):
        self.evtx_table_view.clearContents()
        self.evtx_table_view.setRowCount(0)
        nb_chunk = 0
        evtxInfos = []
        for chunk in chunks:
            events = chunk.events()
            for event in events:
                QCoreApplication.processEvents()
                if node:
                    nodePtr = node.uid()
                elif self.node:
                    nodePtr = self.node.uid()
                else:
                    nodePtr = None
                evtxInfo = EvtxInfo(event, events[event], nb_chunk, nodePtr)
                evtxInfos.append(evtxInfo)
            nb_chunk += 1
        self.addEvents(evtxInfos)

    def display_chunk(self, events):
        self.evtx_table_view.clearContents()
        self.evtx_table_view.setRowCount(0)
        evtxInfos = []
        for event in events:
            for evtx in event:
                QCoreApplication.processEvents()
                evtxInfo = EvtxInfo(evtx, event[evtx], event[evtx]['chunk_nb'],
                                    self.node.uid())
                evtxInfos.append(evtxInfo)

    def dispAdminEvents(self, checked):
        self.evtx_table_view.clearContents()
        if self.display_mode == 0:
            error_list = self.evtx_parser.getEventBylevel(2)
            self.admin_pannel.admin_events.setText("All events")
            tmp_list = self.evtx_parser.getEventBylevel(3)
            error_list.extend(tmp_list)
            self.display_mode = 1
            self.display_chunk(error_list)
        elif self.display_mode == 1:
            self.admin_pannel.admin_events.setText("Admin. events")
            self.display_mode = 0
            processus_manager = ModuleProcessusManager()
            evtx = processus_manager.get('evtx')
            chunks = evtx.data(self.node.uid())
            self.display(chunks, self.node)

    def dispId(self, checked):
        txt = self.admin_pannel.id.text()
        if txt == "":
            return
        try:
            event_list = self.evtx_parser.getEventById(int(txt))
            self.evtx_table_view.clearContents()
            self.evtx_table_view.setRowCount(0)
            self.display_chunk(event_list)
        except ValueError:
            pass

    def dispIdL(self):
        txt = self.admin_pannel.id.text()
        txt = self.admin_pannel.cb.currentText()
        try:
            event_list = self.evtx_parser.getEventById(int(txt))
            self.evtx_table_view.clearContents()
            self.evtx_table_view.setRowCount(0)
            self.display_chunk(event_list)
        except ValueError:
            pass

    def fill_log_viewer(self, item):
        ptr = item.data(QListWidgetItem.UserType)
        node = VFS.Get().getNodeById(ptr.toULongLong()[0])

        processus_manager = ModuleProcessusManager()
        evtx = processus_manager.get('evtx')

        self.node = node
        self.evtx_parser.chunks = evtx.data(ptr.toULongLong()[0])
        self.evtx_parser.node = node

        self.admin_pannel.cb = self.admin_pannel.initId(
            evtx.data(ptr.toULongLong()[0]), 'id')
        self.admin_pannel.cbs = self.admin_pannel.initId(
            evtx.data(ptr.toULongLong()[0]), 'source')

        self.display(evtx.data(ptr.toULongLong()[0]), node)

    def dispDate(self, checked):
        date_begin = str(self.admin_pannel.select_date_b.dateTime().toString(
            "yyyy-MM-ddThh:mm:ss"))
        date_end = str(self.admin_pannel.select_date_e.dateTime().toString(
            "yyyy-MM-ddThh:mm:ss"))
        self.evtx_table_view.clearContents()
        self.evtx_table_view.setRowCount(0)
        event_list = self.evtx_parser.getEventsBetween(date_begin, date_end)
        self.display_chunk(event_list)

    def dispSource(self, checked):
        txt = self.admin_pannel.source.text()

        if txt == "":
            return

        self.evtx_table_view.clearContents()
        self.evtx_table_view.setRowCount(0)
        event_list = self.evtx_parser.getEventBySource(txt)
        self.display_chunk(event_list)

    def dispSourceL(self, checked):
        txt = self.admin_pannel.cbs.currentText()

        self.evtx_table_view.clearContents()
        self.evtx_table_view.setRowCount(0)
        event_list = self.evtx_parser.getEventBySource(txt)
        self.display_chunk(event_list)

    def dispEventType(self, index):
        if index == 0:
            processus_manager = ModuleProcessusManager()
            evtx = processus_manager.get('evtx')
            chunks = evtx.data(self.node.uid())
            self.display(chunks, self.node)
        else:
            self.evtx_table_view.clearContents()
            self.evtx_table_view.setRowCount(0)
            event_list = self.evtx_parser.getEventBylevel(index - 1)
            self.display_chunk(event_list)

    def dispEvent(self, row, column):
        item = self.evtx_table_view.item(row, 4)
        offset_str = item.text()
        offset = int(offset_str)

        item = self.evtx_table_view.item(row, 5)
        chunk_str = item.text()
        chunk_nb = int(chunk_str)

        if self.evtx_table_view.columnCount() == 7:
            item = self.evtx_table_view.item(row,
                                             6).data(QTableWidgetItem.Type)
            n = item.toULongLong()[0]
            self.evtx_parser.node = VFS.Get().getNodeById(n)

        xml = self.evtx_parser.getXML(chunk_nb, offset, self.evtx_parser.node)
        xml_str = tostring(xml, "utf-8")

        self.disp = ViewEvtx()
        self.disp.view.setAlternatingRowColors(1)
        self.disp.view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.disp.view.setSelectionMode(QAbstractItemView.SingleSelection)

        self.current_row = row
        if not row:
            self.disp.prev_evtx.setEnabled(False)

        if row + 1 == self.evtx_table_view.rowCount():
            self.disp.next_evtx.setEnabled(False)

        self.widget = EvtxTree(xml_str, self.disp)

        self.disp.textEdit.setText(self.widget.doc.toString(3))
        self.disp.view.expandAll()
        self.disp.view.resizeColumnToContents(0)

        if PYQT_VERSION_STR >= "4.5.0":
            self.disp.next_evtx.clicked.connect(self.nextEvent)
            self.disp.prev_evtx.clicked.connect(self.prevEvent)

        self.disp.exec_()

        del self.disp
        self.disp = None

    def nextEvent(self, checked):
        row = self.current_row + 1

        self.disp.prev_evtx.setEnabled(True)

        while row + 1 != self.evtx_table_view.rowCount(
        ) and self.evtx_table_view.isRowHidden(row):
            row += 1

        # row = self.current_row

        item = self.evtx_table_view.item(row, 4)
        offset_str = item.text()
        offset = int(offset_str)

        item = self.evtx_table_view.item(row, 5)
        chunk_str = item.text()
        chunk_nb = int(chunk_str)

        node = None
        if self.evtx_table_view.columnCount() == 7:
            item = self.evtx_table_view.item(row, 6)
            node = VFS.Get().getNodeById(long(item.text()))
        else:
            node = self.node

        self.evtx_table_view.setCurrentCell(row, 0)
        xml = self.evtx_parser.getXML(chunk_nb, offset, node)
        xml_str = tostring(xml, "utf-8")

        self.widget = EvtxTree(xml_str, self.disp)

        self.disp.textEdit.setText(self.widget.doc.toString(3))
        self.disp.view.expandAll()
        self.disp.view.resizeColumnToContents(0)

        self.current_row = row

        while row + 1 != self.evtx_table_view.rowCount():
            row += 1
            if not self.evtx_table_view.isRowHidden(row): return

        self.disp.next_evtx.setEnabled(False)

    def prevEvent(self, checked):
        row = self.current_row - 1

        self.disp.next_evtx.setEnabled(True)

        while row != 0 and self.evtx_table_view.isRowHidden(row):
            row -= 1

        item = self.evtx_table_view.item(row, 4)
        offset_str = item.text()
        offset = int(offset_str)

        item = self.evtx_table_view.item(row, 5)
        chunk_str = item.text()
        chunk_nb = int(chunk_str)

        node = None
        if self.evtx_table_view.columnCount() == 7:
            item = self.evtx_table_view.item(row, 6)
            node = VFS.Get().getNodeById(long(item.text()))
        else:
            node = self.node

        self.current_row = row
        self.evtx_table_view.setCurrentCell(self.current_row, 0)

        xml = self.evtx_parser.getXML(chunk_nb, offset, node)
        xml_str = tostring(xml, "utf-8")

        self.widget = EvtxTree(xml_str, self.disp)

        self.disp.textEdit.setText(self.widget.doc.toString(3))
        self.disp.view.expandAll()
        self.disp.view.resizeColumnToContents(0)

        while row != 0:
            row -= 1
            if not self.evtx_table_view.isRowHidden(row): return

        self.disp.prev_evtx.setEnabled(False)
Esempio n. 31
0
class NetCDF3Browser(QWidget):
    """netCDF-Browser"""

    def __init__(self):
        QWidget.__init__(self)
        self.layout = QVBoxLayout(self)
        self.layout.setSpacing(0)
        self.layout.setMargin(0)

        self.toolBar = QFrame(self)
        self.toolBarLayout = QHBoxLayout(self.toolBar)
        self.toolBarLayout.setMargin(2)
        self.toolBarLayout.setSpacing(2)
        self.layout.addWidget(self.toolBar)

        self.loadButton = QToolButton(self.toolBar)
        self.loadButton.setText(QCoreApplication.translate('NetCDF3', 'Open...'))
        self.loadButton.setIcon(QIcon(QPixmap(SimuVis4.Icons.fileOpen)))
        self.loadButton.setToolTip(QCoreApplication.translate('NetCDF3', 'Open a netCDF3 file'))
        self.toolBarLayout.addWidget(self.loadButton)
        self.connect(self.loadButton, SIGNAL('pressed()'), self.loadFile)

        self.dropButton = QToolButton(self.toolBar)
        self.dropButton.setText(QCoreApplication.translate('NetCDF3', 'Close All'))
        self.dropButton.setIcon(QIcon(QPixmap(SimuVis4.Icons.clear)))
        self.dropButton.setToolTip(QCoreApplication.translate('NetCDF3', 'Drop all open netCDF3 files'))
        self.toolBarLayout.addWidget(self.dropButton)
        self.connect(self.dropButton, SIGNAL('pressed()'), self.dropFiles)
        self.dropButton.setEnabled(False)

        self.toolBarLayout.addStretch(100)

        self.splitter = QSplitter(self)
        self.splitter.setOrientation(Qt.Vertical)
        self.treeView = QTreeView(self.splitter)
        self.treeView.setAlternatingRowColors(True)
        self.treeView.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.textBrowser = QTextBrowser(self.splitter)
        self.layout.addWidget(self.splitter)
        self.splitter.setStretchFactor(0, 90)
        self.splitter.setStretchFactor(1, 10)
        self.model = NetCDF3Model()
        self.treeView.setModel(self.model)
        self.treeView.setSortingEnabled(True)
        self.treeView.expandAll()
        self.connect(self.treeView.selectionModel(), SIGNAL("currentChanged(QModelIndex, QModelIndex)"), self.showItem)
        self.connect(self.treeView, SIGNAL("doubleClicked(QModelIndex)"), self.itemAction)

        ftActions = SimuVis4.Globals.fileTypeActions
        ftActions.addAction(self.loadFile, ('application/x-netcdf',),
            QCoreApplication.translate('NetCDF3', 'Open in netCDF3 browser'), 10)

    def loadFile(self, fn=None):
        if not fn:
            fn = QFileDialog.getOpenFileName(self, QCoreApplication.translate('NetCDF3', "Select netCDF3 file to open"),
                SimuVis4.Globals.defaultFolder)
            if not fn.isEmpty():
                fn = unicode(fn)
                SimuVis4.Globals.defaultFolder, tmp = os.path.split(fn)
            else:
                return
        self.model.addNcFile(fn)
        SimuVis4.Globals.dataBrowser.toolBox.setCurrentWidget(self)

    def dropFiles(self):
        # FIXME: ...
        pass

    def itemAction(self, mi,):
        # FIXME: use a MIME-Handler here
        i = self.model.itemFromIndex(mi)
        t, nc = i.ncItem
        QMessageBox.information(self,
                QCoreApplication.translate('NetCDF3', 'netCDF3: Item clicked'),
                QCoreApplication.translate('NetCDF3', 'You clicked an item in the netCDF3-browser'))

    def showItem(self, mi, pr):
        i = self.model.itemFromIndex(mi)
        t, nc = i.ncItem
        txt = ""
        name = str(i.data().toString())
        if t == 'F':
            p, f = os.path.split(name)
            txt = "<i>File </i><b>%s</b><br> in %s" % (f, p)
        elif t == 'A':
            txt = "<i>Attribute </i><b>%s:</b><br>%s" % (name, escape(unicode(nc)))
        elif t == 'D':
            txt = "<i>Dimension </i><b>%s:</b><br>%s" % (name, str(nc))
        elif t == 'V':
            txt = "<i>Variable </i><b>%s:</b><br>Typecode: %s<br>Dimensions: %s<br>Shape: %s" % \
                (name, nc.typecode(), '*'.join(d for d in nc.dimensions), nc.shape)
        else:
            return
        self.textBrowser.setText(txt)
Esempio n. 32
0
class DSBrowser(QWidget):
    """browser for datastorage databases
       Nodes are identified by a string, containing fields separated by '|'.
       - first filed is a capital letter:
       'R'oot, 'P'roject, sensor'G'roup, 'S'ensor and 'C'hart
       - second field is the database folder
       - third filed is the path of the node in the database
       - for charts the fourth field is the chart name (third is path of sensorgroup in this case)
    """
    def __init__(self):
        QWidget.__init__(self)
        self.layout = QVBoxLayout(self)
        self.layout.setSpacing(0)
        self.layout.setMargin(0)

        self.toolBar = QFrame(self)
        self.toolBarLayout = QHBoxLayout(self.toolBar)
        self.toolBarLayout.setMargin(2)
        self.toolBarLayout.setSpacing(2)
        self.layout.addWidget(self.toolBar)

        self.loadButton = QToolButton(self.toolBar)
        self.loadButton.setText(QCoreApplication.translate('DataStorageBrowser', 'Open...'))
        self.loadButton.setIcon(QIcon(QPixmap(SimuVis4.Icons.fileOpen)))
        self.loadButton.setToolTip(QCoreApplication.translate('DataStorageBrowser', 'Open a datastorage database'))
        self.toolBarLayout.addWidget(self.loadButton)
        self.connect(self.loadButton, SIGNAL('pressed()'), self.loadDatabase)

        self.expandButton = QToolButton(self.toolBar)
        self.expandButton.setText('Expand/Collapse')
        self.expandButton.setIcon(QIcon(QPixmap(Icons.exp_col)))
        self.expandButton.setToolTip(QCoreApplication.translate('DataStorageBrowser', 'Expand or collapse the whole tree'))
        self.toolBarLayout.addWidget(self.expandButton)
        self.connect(self.expandButton, SIGNAL('pressed()'), self.expandCollapseAll)

        self.searchInput = QLineEdit(self.toolBar)
        self.searchInput.setText(QCoreApplication.translate('DataStorageBrowser', 'Enter search text here'))
        self.searchInput.setToolTip(QCoreApplication.translate('DataStorageBrowser',
            'Enter search text using wildcards here, press ENTER again to go to next match!'))
        self.toolBarLayout.addWidget(self.searchInput, 100)
        self.connect(self.searchInput, SIGNAL('returnPressed()'), self.searchItem)

        self.helpButton = QToolButton(self.toolBar)
        self.helpButton.setText(QCoreApplication.translate('DataStorageBrowser', 'Help'))
        self.helpButton.setIcon(QIcon(QPixmap(SimuVis4.Icons.help)))
        self.helpButton.setToolTip(QCoreApplication.translate('DataStorageBrowser', 'Show help for DataStorageBrowser'))
        self.toolBarLayout.addWidget(self.helpButton)
        self.connect(self.helpButton, SIGNAL('pressed()'), self.showHelp)

        self.splitter = QSplitter(self)
        self.splitter.setOrientation(Qt.Vertical)
        self.treeView = QTreeView(self.splitter)
        self.treeView.setAlternatingRowColors(True)
        self.treeView.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.treeView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.treeView.setAutoExpandDelay(500)
        self.textBrowser = QTextBrowser(self.splitter)
        self.layout.addWidget(self.splitter)
        self.splitter.setStretchFactor(0, 60)
        self.splitter.setStretchFactor(1, 40)
        self.model = DSModel()
        self.treeView.setModel(self.model)
        self.treeView.setSortingEnabled(True)
        self.treeView.expandAll()
        self.connect(self.treeView.selectionModel(), SIGNAL("currentChanged(QModelIndex, QModelIndex)"), self.showItem)
        self.connect(self.treeView, SIGNAL("doubleClicked(QModelIndex)"), self.itemAction)
        self.connect(self.treeView, SIGNAL("customContextMenuRequested(QPoint)"), self.showContextMenu)
        self.selectedNode = None
        self.selectedMI = None
        self.searchText = ''
        self.searchResults = []
        self.collExpand = SimuVis4.Misc.Switcher()


    def loadDatabase(self, dn=None):
        """load a database"""
        if not dn:
            dn = QFileDialog.getExistingDirectory(self, QCoreApplication.translate('DataStorageBrowser',
                "Select a folder containing a datastorage database"), SimuVis4.Globals.defaultFolder)
            if not dn.isEmpty():
                dn = unicode(dn)
                SimuVis4.Globals.defaultFolder = dn
            else:
                return
        self.model.addDatabase(dn)
        self.treeView.expandToDepth(1)
        self.treeView.resizeColumnToContents(0)


    def showHelp(self):
        SimuVis4.HelpBrowser.showHelp('/plugin/DataStorageBrowser/index.html')


    def showItem(self, mi, pr):
        """show the item at model index mi"""
        t, n = self.model.dsNode(mi)
        txt = ""
        if t == 'R':
            # FIXME: no metadata?
            txt = rootInfo.substitute(name=n.name, title=escape(n.title), folder=n.h5dir,
                projects=len(n)) + formatMetaData(n)
        elif t == 'P':
            txt = projectInfo.substitute(name=n.name, path=escape(n.parent.name),
                title=escape(n.title), groups=len(n)) + formatMetaData(n)
        elif t == 'G':
            txt = groupInfo.substitute(name=n.name,  path='/'.join(n.path.split('/')[:-1]),
                title=escape(n.title), sensors=len(n), charts=len(n.charts)) + formatMetaData(n)
        elif t == 'S':
            txt = sensorInfo.substitute(name=n.name,  path='/'.join(n.path.split('/')[:-1]),
                title=escape(n.title), start=n.timegrid.start, stop=n.timegrid.stop,
                step=n.timegrid.step, length=n.datalen()) + formatMetaData(n)
        elif t == 'C':
            txt = chartInfo.substitute(name=n.name, path=n.sensorgroup.path)
        self.textBrowser.setText(txt)


    def searchItem(self):
        """execute the search and highlight the (next) result"""
        txt = str(self.searchInput.text())
        if txt != self.searchText:
            self.searchText = txt
            tmp = self.model.findItems(txt,
                Qt.MatchFixedString | Qt.MatchContains | Qt.MatchWildcard | Qt.MatchRecursive)
            self.searchList = [i.index() for i in tmp]
        if self.searchList:
            mi = self.searchList.pop()
            self.treeView.setCurrentIndex(mi)
            self.treeView.expand(mi)
            self.treeView.scrollTo(mi)
        else:
            QMessageBox.information(self, QCoreApplication.translate('DataStorageBrowser',
                'No (more) matches!'), QCoreApplication.translate('DataStorageBrowser',
                'No (more) matches found! Change you search criteria and try again!'))
            self.searchText = ''


    def expandCollapseAll(self):
        if self.collExpand():
            self.treeView.collapseAll()
        else:
            self.treeView.expandAll()

    def itemAction(self, mi):
        """default action (on doubleclick) for item at model index mi"""
        t, n = self.model.dsNode(mi)
        if t == 'R':
            pass
        elif t == 'P':
            pass
        elif t == 'G':
            pass
        elif t == 'S':
            self.showQwtPlot(n)
        elif t == 'C':
            self.showMplChart(n)


    def showContextMenu(self, pos):
        """show context menu for item at pos"""
        mi = self.treeView.indexAt(pos)
        t, n = self.model.dsNode(mi)
        self.selectedNode = n
        self.selectedMI = mi
        m = QMenu()
        if t == 'R':
            m.addAction(QCoreApplication.translate('DataStorageBrowser', 'Close'), self.closeDatabase)
        elif t == 'P':
            pass
        elif t == 'G':
            nCharts = len(n.charts)
            if nCharts > 0:
                txt = str(QCoreApplication.translate('DataStorageBrowser', 'Show all Charts (%d)')) % nCharts
                m.addAction(txt, self.showAllCharts)
            m.addAction(QCoreApplication.translate('DataStorageBrowser', 'Add Chart'), self.newChart)
        elif t == 'S':
            m.addAction(QCoreApplication.translate('DataStorageBrowser', 'Plot (Qwt)'), self.showQwtPlot)
        elif t == 'C':
            m.addAction(QCoreApplication.translate('DataStorageBrowser', 'Show'), self.showMplChart)
            m.addAction(QCoreApplication.translate('DataStorageBrowser', 'Delete'), self.deleteItem)
        if t in 'RPGS':
            m.addSeparator()
            m.addAction(QCoreApplication.translate('DataStorageBrowser', 'Edit metadata'), self.editMetadata)
        a = m.exec_(self.treeView.mapToGlobal(pos))


    def showMplChart(self, node=None):
        if node is None:
            node = self.selectedNode
        showChartMplWindow(node, maximized=showChartMaximized)


    def showAllCharts(self, node=None):
        if node is None:
            node = self.selectedNode
        for chart in node.charts.values():
            showChartMplWindow(chart, maximized=showChartMaximized)


    def showQwtPlot(self, node=None):
        if node is None:
            node = self.selectedNode
        showQwtPlotWindow(node, maximized=showChartMaximized)


    def editMetadata(self, node=None):
        if node is None:
            node = self.selectedNode
        editMetadata(node)


    def closeDatabase(self, mi=None):
        if mi is None:
            mi = self.selectedMI
        self.model.closeDatabase(mi)


    def newChart(self, mi=None):
        """add a chart to sensorgroup at mi using the wizard"""
        if mi is None:
            mi = self.selectedMI
        showNewChartWizard(self.model, mi)


    def deleteItem(self, mi=None):
        """delete the item at mi"""
        if mi is None:
            mi = self.selectedMI
        self.model.deleteItem(mi)