class SummarySection(QTabWidget):
  """
  Represents the summary section.
  Takes reply data from main ui and updates it's tabs
  Keeps track of cumulative summary data.
  """
  def __init__(self, parent=None):
    super(SummarySection, self).__init__(parent)
    self.text_edit_summary = QTextEdit()
    self.text_edit_summary.setReadOnly(True)
    self.addTab(self.text_edit_summary, "Output")
    self.ball_grid = BallGrid(30, 30, 2)
    self.addTab(self.ball_grid, "Led View")
    self.tab_summary = SummaryTab()
    self.addTab(self.tab_summary, "Summary")
    #some private fields, keep track of accumulated summary data
    self.current_ip = 0 #we take reply data for ips in order
    self.sent_packets = 0
    self.received_packets = 0
    self.average_delay = 0
    
  def setIPs(self, ips):
    #this indicates the start of a new ping, could be treated
    #as a pingStarted signal
    self.current_ip = 0
    self.sent_packets = 0
    self.received_packets = 0
    self.average_delay = 0
    self.text_edit_summary.clear()
    self.ball_grid.layoutForIps(ips)
    self.tab_summary.zeroOut()
  
  def takeReplyData(self, replyData, sentPackets): #sent packets is passed in as extra
    """
    Update the output text area with the replyData string representation
    Set proper widget states on the BallGrid
    Calculate summaries cumulatively and set them for display on the summary tab 
    """
    self.text_edit_summary.append(str(replyData))
    packets_lost = replyData.packets_lost
    if packets_lost:
      self.ball_grid.setStateAt(self.current_ip, BallWidget.UNREACHABLE)
    else:
      self.ball_grid.setStateAt(self.current_ip, BallWidget.REACHABLE)
    self.current_ip += 1
    self.sent_packets += sentPackets 
    self.received_packets = self.sent_packets - replyData.packets_lost
    self.average_delay += (replyData.rtt / self.current_ip) #the current_ip reflects the overall number of replies
    summary_data = SummaryData(self.sent_packets, self.received_packets, self.average_delay)
    self.tab_summary.setSummaryData(summary_data)
    
  def pingingStoppedHandler(self):
    self.ball_grid.pingingCancelledHandler()
Beispiel #2
0
 def license_(self):
     lic = QTextEdit(self)
     lic.setWindowFlags(Qt.Window)
     lic.setWindowTitle("QReduce FreeBSD License")
     font = lic.font()
     font.setFamily('')
     font.setFixedPitch(True)
     font.setKerning(0)
     font.setWeight(QFont.Normal)
     font.setItalic(False)
     lic.setFont(font)
     lic.setText(
         'Copyright (c) 2009-2014 T. Sturm, 2010 C. Zengler'
         '<p>'
         'All rights reserved.'
         '<p>'
         'Redistribution and use in source and binary forms, with '
         'or without modification, are permitted provided that the '
         'following conditions are met:'
         '<ol>'
         '<li>Redistributions of source code must retain the relevant '
         'copyright notice, this list of conditions and the following '
         'disclaimer. '
         '<p>'
         '<li>Redistributions in binary form must reproduce the above '
         'copyright notice, this list of conditions and the following '
         'disclaimer in the documentation and/or other materials '
         'provided with the distribution. '
         '</ol>'
         '<p>'
         'THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND '
         'CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, '
         'INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF '
         'MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE '
         'DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNERS OR '
         'CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, '
         'SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT '
         'NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; '
         'LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) '
         'HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN '
         'CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR '
         'OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS '
         'SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.'
         '</span>')
     lic.setReadOnly(True)
     w = 66 * lic.fontMetrics().width('m')
     h = 36 * lic.fontMetrics().height()
     lic.resize(w,h)
     lic.show()
     lic.raise_()
Beispiel #3
0
 def testRefcount(self):
     textedit = QTextEdit()
     textedit.setReadOnly(True)
     doc = textedit.document()
     cursor = QTextCursor(doc)
     cursor.insertText("PySide Rocks")
     ud = TestUserData({"Life": 42})
     self.assertEqual(sys.getrefcount(ud), 2)
     cursor.block().setUserData(ud)
     self.assertEqual(sys.getrefcount(ud), 3)
     ud2 = cursor.block().userData()
     self.assertEqual(sys.getrefcount(ud), 4)
     self.udata = weakref.ref(ud, None)
     del ud, ud2
     self.assertEqual(sys.getrefcount(self.udata()), 2)
Beispiel #4
0
 def testRefcount(self):
     textedit = QTextEdit()
     textedit.setReadOnly(True)
     doc = textedit.document()
     cursor = QTextCursor(doc)
     cursor.insertText("PySide Rocks")
     ud = TestUserData({"Life": 42})
     self.assertEqual(sys.getrefcount(ud), 2)
     cursor.block().setUserData(ud)
     self.assertEqual(sys.getrefcount(ud), 3)
     ud2 = cursor.block().userData()
     self.assertEqual(sys.getrefcount(ud), 4)
     self.udata = weakref.ref(ud, None)
     del ud, ud2
     self.assertEqual(sys.getrefcount(self.udata()), 2)
Beispiel #5
0
    def create_text_input(
        self, parent, read_only=False, password=False, handle_enter=False, multi_line=False, align="left"
    ):
        """ Returns an adapted single or mutli line text input control.
        """
        if multi_line:
            control = QTextEdit(check_parent(parent))
        else:
            control = QLineEdit(check_parent(parent))
            control.setAlignment(horizontal_alignment_styles[align] | Qt.AlignVCenter)
            if password:
                control.setEchoMode(QLineEdit.Password)

        control.setReadOnly(read_only)

        return control_adapter_for(control)
 def __init__(self, certText, parent=None):
     try:
         super(ShowCertWindow, self).__init__(parent=parent)
         qWidget = QWidget()
         layout = QVBoxLayout(qWidget)
         textEdit = QTextEdit()
         textEdit.setReadOnly(True)
         textEdit.setPlainText(certText)
         layout.addWidget(textEdit)
         button = QPushButton("OK")
         button.clicked.connect(self.destroy)
         layout.addWidget(button)
         self.setGeometry(300, 300, 500, 300)
         self.setWindowTitle("CA Certificate")
         self.setCentralWidget(qWidget)
         self.show()
     except e:
         print(e)
class ConsoleDialog(QtGui.QDialog):
    def __init__(self, stream=None):
        QtGui.QDialog.__init__(self)

        self.stream = stream
        self.setWindowTitle('Console Messages')
        self.layout = QHBoxLayout(self)
        self.layout.setSpacing(6)
        self.layout.setContentsMargins(3, 3, 3, 3)
        self.edit = QTextEdit(self)
        self.edit.setReadOnly(True)
        self.layout.addWidget(self.edit)
        self.resize(450, 250)

    def write(self, msg):
        self.edit.moveCursor(QtGui.QTextCursor.End)
        self.edit.insertPlainText(msg)
        if self.stream:
            self.stream.write(msg)
Beispiel #8
0
 def make_source(self, name):
     self.compiler_view.addItem(name)
     self.compiler_view.setCurrentRow(0)
     scrollbar_width = QApplication.style().pixelMetric(
         QStyle.PM_ScrollBarExtent)
     self.compiler_view.setMaximumWidth(
         self.compiler_view.sizeHintForColumn(0) + scrollbar_width + 16)
     page = QWidget()
     QHBoxLayout(page)
     page.layout().setContentsMargins(*(0,) * 4)
     source = QTextEdit()
     source.setStyleSheet('min-width: 0; min-height: 0')
     source.setReadOnly(True)
     QVBoxLayout(source)
     button = QPushButton('Copy')
     button.clicked.connect(functools.partial(self.set_clipboard, source))
     page.layout().addWidget(source)
     source.layout().addWidget(button, 0, Qt.AlignRight | Qt.AlignBottom)
     self.stacked_widget.addWidget(page)
     return source
class SurfaceLandmarkWidget(QWidget):
	def __init__(self):
		super(SurfaceLandmarkWidget, self).__init__()
		
		self.textFrame = QTextEdit("<p>Hold your mouse over the volume "
			"to move the locator. To create a landmark, press 'Space'.</p>"
			"<p>When you want to proceed to the following landmark, "
			"click the 'Done' button behind the landmark pair in the "
			"center of the window.</p>")
		self.textFrame.setReadOnly(True)
		self.textFrame.setFrameShape(QFrame.NoFrame)
		self.textFrame.setAutoFillBackground(False)
		self.textFrame.setAttribute(Qt.WA_TranslucentBackground)
		self.textFrame.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
		self.textFrame.setStyleSheet("background: #aaa")

		layout = QGridLayout()
		layout.setAlignment(Qt.AlignTop)
		layout.setSpacing(0)
		layout.setContentsMargins(0, 0, 0, 0)
		layout.addWidget(self.textFrame)
		self.setLayout(layout)
Beispiel #10
0
class SurfaceLandmarkWidget(QWidget):
    def __init__(self):
        super(SurfaceLandmarkWidget, self).__init__()

        self.textFrame = QTextEdit(
            "<p>Hold your mouse over the volume "
            "to move the locator. To create a landmark, press 'Space'.</p>"
            "<p>When you want to proceed to the following landmark, "
            "click the 'Done' button behind the landmark pair in the "
            "center of the window.</p>")
        self.textFrame.setReadOnly(True)
        self.textFrame.setFrameShape(QFrame.NoFrame)
        self.textFrame.setAutoFillBackground(False)
        self.textFrame.setAttribute(Qt.WA_TranslucentBackground)
        self.textFrame.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.textFrame.setStyleSheet("background: #aaa")

        layout = QGridLayout()
        layout.setAlignment(Qt.AlignTop)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.textFrame)
        self.setLayout(layout)
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):

        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(810, 492)

        lbMinWidth = 65
        lbMinWidthLogin = 110
        # leMinWidth = 200

        # self.centralwidget = QWidget(MainWindow)
        self.mainSplitter = QSplitter(Qt.Horizontal, MainWindow)
        self.mainSplitter.setObjectName("centralwidget")
        self.mainSplitter.setProperty("childrenCollapsible", False)
        MainWindow.setCentralWidget(self.mainSplitter)

        self.leftSplitter = QSplitter(Qt.Vertical, self.mainSplitter)
        self.leftSplitter.setProperty("childrenCollapsible", False)

        # login_gbox
        self.login_gbox = QGroupBox(self.leftSplitter)
        self.login_gbox.setFlat(True)
        self.login_gbox.setObjectName("login_gbox")

        login_gbox_layout = QVBoxLayout(self.login_gbox)
        login_gbox_presets_layout = QHBoxLayout()
        login_gbox_server_layout = QHBoxLayout()
        login_gbox_ssl_layout = QHBoxLayout()
        login_gbox_address_layout = QHBoxLayout()
        login_gbox_pass_layout = QHBoxLayout()
        login_gbox_connect_layout = QHBoxLayout()
        login_gbox_layout.addLayout(login_gbox_presets_layout)
        login_gbox_layout.addLayout(login_gbox_server_layout)
        login_gbox_layout.addLayout(login_gbox_ssl_layout)
        login_gbox_layout.addLayout(login_gbox_address_layout)
        login_gbox_layout.addLayout(login_gbox_pass_layout)
        login_gbox_layout.addLayout(login_gbox_connect_layout)

        self.lb_presets = QLabel(self.login_gbox)
        self.lb_presets.setObjectName("lb_presets")
        self.lb_presets.setMinimumWidth(lbMinWidthLogin)
        self.lb_presets.setMaximumWidth(lbMinWidthLogin)
        self.presets_cbox = QComboBox(self.login_gbox)
        self.presets_cbox.setObjectName("presets_cbox")
        self.add_preset_btn = QPushButton(self.login_gbox)
        self.add_preset_btn.setObjectName("add_preset_btn")
        self.add_preset_btn.setMaximumWidth(30)
        self.remove_preset_btn = QPushButton(self.login_gbox)
        self.remove_preset_btn.setObjectName("remove_preset_btn")
        self.remove_preset_btn.setMaximumWidth(20)
        login_gbox_presets_layout.addWidget(self.lb_presets)
        login_gbox_presets_layout.addWidget(self.presets_cbox)
        login_gbox_presets_layout.addWidget(self.add_preset_btn)
        login_gbox_presets_layout.addWidget(self.remove_preset_btn)

        self.lb_imap_server = QLabel(self.login_gbox)
        self.lb_imap_server.setObjectName("lb_imap_server")
        self.lb_imap_server.setMinimumWidth(lbMinWidthLogin)
        self.imap_server_le = QLineEdit(self.login_gbox)
        self.imap_server_le.setObjectName("imap_server_le")
        login_gbox_server_layout.addWidget(self.lb_imap_server)
        login_gbox_server_layout.addWidget(self.imap_server_le)

        self.lb_ssl = QLabel(self.login_gbox)
        self.lb_ssl.setObjectName("lb_ssl")
        self.lb_ssl.setMinimumWidth(lbMinWidthLogin)
        self.lb_ssl.setMaximumWidth(lbMinWidthLogin)
        self.ssl_cb = QCheckBox(self.login_gbox)
        self.ssl_cb.setEnabled(False)
        self.ssl_cb.setCheckable(True)
        self.ssl_cb.setChecked(True)
        self.ssl_cb.setObjectName("ssl_cb")
        login_gbox_ssl_layout.addWidget(self.lb_ssl)
        login_gbox_ssl_layout.addWidget(self.ssl_cb)

        self.lb_adress = QLabel(self.login_gbox)
        self.lb_adress.setObjectName("lb_adress")
        self.lb_adress.setMinimumWidth(lbMinWidthLogin)
        self.adress_le = QLineEdit(self.login_gbox)
        self.adress_le.setInputMethodHints(Qt.ImhNone)
        self.adress_le.setObjectName("adress_le")
        login_gbox_address_layout.addWidget(self.lb_adress)
        login_gbox_address_layout.addWidget(self.adress_le)

        self.lb_pass = QLabel(self.login_gbox)
        self.lb_pass.setObjectName("lb_pass")
        self.lb_pass.setMinimumWidth(lbMinWidthLogin)
        self.pass_le = QLineEdit(self.login_gbox)
        self.pass_le.setText("")
        self.pass_le.setEchoMode(QLineEdit.Password)
        self.pass_le.setObjectName("pass_le")
        login_gbox_pass_layout.addWidget(self.lb_pass)
        login_gbox_pass_layout.addWidget(self.pass_le)

        self.connect_btn = QPushButton(self.login_gbox)
        self.connect_btn.setObjectName("connect_btn")
        login_gbox_connect_layout.addStretch()
        login_gbox_connect_layout.addWidget(self.connect_btn)

        # search_gbox
        self.search_gbox = QGroupBox(self.leftSplitter)
        self.search_gbox.hide()
        self.search_gbox.setObjectName("search_gbox")

        search_gbox_layout = QVBoxLayout(self.search_gbox)
        search_gbox_mailbox_layout = QVBoxLayout()
        search_gbox_date_layout = QHBoxLayout()
        search_gbox_from_layout = QHBoxLayout()
        search_gbox_to_layout = QHBoxLayout()
        search_gbox_subject_layout = QHBoxLayout()
        search_gbox_threads_layout = QHBoxLayout()
        search_gbox_paramaters_layout = QHBoxLayout()

        search_gbox_layout.addLayout(search_gbox_mailbox_layout)
        search_gbox_layout.addLayout(search_gbox_date_layout)
        search_gbox_layout.addLayout(search_gbox_from_layout)
        search_gbox_layout.addLayout(search_gbox_to_layout)
        search_gbox_layout.addLayout(search_gbox_subject_layout)
        search_gbox_layout.addLayout(search_gbox_threads_layout)
        search_gbox_layout.addLayout(search_gbox_paramaters_layout)

        self.lb_select_mailbox = QLabel(self.search_gbox)
        self.lb_select_mailbox.setObjectName("lb_select_mailbox")
        self.mailboxes_lw = QListWidget(self.search_gbox)
        self.mailboxes_lw.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.mailboxes_lw.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.mailboxes_lw.setObjectName("mailboxes_lw")
        search_gbox_mailbox_layout.addWidget(self.lb_select_mailbox)
        search_gbox_mailbox_layout.addWidget(self.mailboxes_lw)

        self.since_date_cb = QCheckBox(self.search_gbox)
        self.since_date_cb.setObjectName("since_date_cb")
        self.since_date_cb.setMinimumWidth(lbMinWidth)
        self.since_date_cb.setMaximumWidth(lbMinWidth)
        self.since_date_edit = QDateEdit(self.search_gbox)
        self.since_date_edit.setCalendarPopup(True)
        self.since_date_edit.setObjectName("since_date_edit")
        self.since_date_edit.setDate(QDate.currentDate().addDays(-365))
        self.since_date_edit.setMaximumDate(QDate.currentDate())
        self.since_date_edit.setEnabled(False)
        self.before_date_cb = QCheckBox(self.search_gbox)
        self.before_date_cb.setObjectName("before_date_cb")
        self.before_date_cb.setMinimumWidth(70)
        self.before_date_cb.setMaximumWidth(70)
        self.before_date_edit = QDateEdit(self.search_gbox)
        self.before_date_edit.setCalendarPopup(True)
        self.before_date_edit.setObjectName("before_date_edit")
        self.before_date_edit.setDate(QDate.currentDate())
        self.before_date_edit.setMaximumDate(QDate.currentDate())
        self.before_date_edit.setEnabled(False)
        search_gbox_date_layout.addWidget(self.since_date_cb)
        search_gbox_date_layout.addWidget(self.since_date_edit)
        search_gbox_date_layout.addWidget(self.before_date_cb)
        search_gbox_date_layout.addWidget(self.before_date_edit)

        self.lb_from = QLabel(self.search_gbox)
        self.lb_from.setObjectName("lb_from")
        self.lb_from.setMinimumWidth(lbMinWidth)
        self.from_le = QLineEdit(self.search_gbox)
        self.from_le.setObjectName("from_le")
        search_gbox_from_layout.addWidget(self.lb_from)
        search_gbox_from_layout.addWidget(self.from_le)

        self.lb_to = QLabel(self.search_gbox)
        self.lb_to.setObjectName("lb_to")
        self.lb_to.setMinimumWidth(lbMinWidth)
        self.to_le = QLineEdit(self.search_gbox)
        self.to_le.setObjectName("to_le")
        search_gbox_to_layout.addWidget(self.lb_to)
        search_gbox_to_layout.addWidget(self.to_le)

        self.lb_subject = QLabel(self.search_gbox)
        self.lb_subject.setObjectName("lb_subject")
        self.lb_subject.setMinimumWidth(lbMinWidth)
        self.subject_le = QLineEdit(self.search_gbox)
        self.subject_le.setObjectName("subject_le")
        search_gbox_subject_layout.addWidget(self.lb_subject)
        search_gbox_subject_layout.addWidget(self.subject_le)

        # self.lb_threads = QLabel(self.search_gbox)
        # self.lb_threads.setObjectName("lb_threads")
        # self.lb_threads.setMaximumWidth(lbMinWidth)
        # self.thread_count_sb = QSpinBox(self.search_gbox)
        # self.thread_count_sb.setMinimum(1)
        # self.thread_count_sb.setMaximum(10)
        # self.thread_count_sb.setObjectName("thread_count_sb")
        self.html_radio = QRadioButton(self.search_gbox)
        self.html_radio.setObjectName("html_radio")
        self.text_radio = QRadioButton(self.search_gbox)
        self.text_radio.setObjectName("text_radio")
        self.extactTypeButtonGroup = QButtonGroup(self)
        self.extactTypeButtonGroup.addButton(self.html_radio)
        self.extactTypeButtonGroup.addButton(self.text_radio)
        self.html_radio.setChecked(True)
        self.search_btn = QPushButton(self.search_gbox)
        self.search_btn.setObjectName("search_btn")
        # search_gbox_threads_layout.addWidget(self.lb_threads)
        # search_gbox_threads_layout.addWidget(self.thread_count_sb)
        search_gbox_threads_layout.addStretch()
        search_gbox_threads_layout.addWidget(self.html_radio)
        search_gbox_threads_layout.addWidget(self.text_radio)
        # search_gbox_threads_layout.addStretch()
        search_gbox_threads_layout.addWidget(self.search_btn)

        self.parameters_cb = QCheckBox(self.search_gbox)
        self.parameters_cb.setText("")
        self.parameters_cb.setObjectName("parameters_cb")
        self.parameters_le = QLineEdit(self.search_gbox)
        self.parameters_le.setEnabled(False)
        self.parameters_le.setObjectName("parameters_le")
        search_gbox_paramaters_layout.addWidget(self.parameters_cb)
        search_gbox_paramaters_layout.addWidget(self.parameters_le)

        # log_gbox
        self.log_gbox = QGroupBox(self.leftSplitter)
        self.log_gbox.setFlat(True)
        self.log_gbox.setObjectName("log_gbox")
        log_layout = QVBoxLayout(self.log_gbox)
        self.log_te = QTextEdit(self.log_gbox)
        self.log_te.setLineWrapMode(QTextEdit.NoWrap)
        self.log_te.setReadOnly(True)
        self.log_te.setTextInteractionFlags(Qt.TextSelectableByKeyboard | Qt.TextSelectableByMouse)
        self.log_te.setObjectName("log_te")

        self.disconnect_btn = QPushButton(self.log_gbox)
        self.disconnect_btn.setObjectName("disconnect_btn")
        self.disconnect_btn.hide()
        log_layout.addWidget(self.log_te)
        log_layout_btn = QHBoxLayout()
        log_layout.addLayout(log_layout_btn)
        log_layout_btn.addWidget(self.disconnect_btn)
        log_layout_btn.addStretch()

        # links_gbox
        self.links_gbox = QGroupBox(self.mainSplitter)
        self.links_gbox.setFlat(True)
        self.links_gbox.setObjectName("links_gbox")
        links_gbox_layout = QVBoxLayout(self.links_gbox)
        links_gbox_links_layout = QVBoxLayout()
        links_gbox_buttons_layout = QHBoxLayout()
        links_gbox_layout.addLayout(links_gbox_links_layout)
        links_gbox_layout.addLayout(links_gbox_buttons_layout)

        self.links_text_edit = QTextEdit(self.links_gbox)
        self.links_text_edit.setObjectName("links_text_edit")
        links_gbox_links_layout.addWidget(self.links_text_edit)

        self.export_txt_btn = QPushButton(self.links_gbox)
        self.export_txt_btn.setObjectName("export_txt_btn")
        self.export_txt_btn.setEnabled(False)
        self.export_html_btn = QPushButton(self.links_gbox)
        self.export_html_btn.setObjectName("export_html_btn")
        self.export_html_btn.setEnabled(False)

        links_gbox_buttons_layout.addWidget(self.export_txt_btn)
        links_gbox_buttons_layout.addWidget(self.export_html_btn)

        # menubar
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setObjectName("menubar")
        self.menu_file = QMenu(self.menubar)
        self.menu_file.setObjectName("menu_file")
        self.menu_about = QMenu(self.menubar)
        self.menu_about.setObjectName("menu_about")
        MainWindow.setMenuBar(self.menubar)
        self.action_about = QAction(MainWindow)
        self.action_about.setObjectName("action_about")
        self.action_About_Qt = QAction(MainWindow)
        self.action_About_Qt.setObjectName("action_About_Qt")
        self.action_exit = QAction(MainWindow)
        self.action_exit.setObjectName("action_exit")
        self.actionSave = QAction(MainWindow)
        self.actionSave.setObjectName("actionSave")
        self.menu_file.addAction(self.action_exit)
        self.menu_about.addAction(self.action_about)
        self.menu_about.addAction(self.action_About_Qt)
        self.menubar.addAction(self.menu_file.menuAction())
        self.menubar.addAction(self.menu_about.menuAction())

        self.retranslateUi(MainWindow)
        QMetaObject.connectSlotsByName(MainWindow)
        MainWindow.setTabOrder(self.presets_cbox, self.imap_server_le)
        MainWindow.setTabOrder(self.imap_server_le, self.adress_le)
        MainWindow.setTabOrder(self.adress_le, self.pass_le)
        MainWindow.setTabOrder(self.pass_le, self.connect_btn)
        MainWindow.setTabOrder(self.connect_btn, self.log_te)
        MainWindow.setTabOrder(self.log_te, self.since_date_cb)
        MainWindow.setTabOrder(self.since_date_cb, self.since_date_edit)
        MainWindow.setTabOrder(self.since_date_edit, self.before_date_cb)
        MainWindow.setTabOrder(self.before_date_cb, self.before_date_edit)
        MainWindow.setTabOrder(self.before_date_edit, self.mailboxes_lw)
        MainWindow.setTabOrder(self.mailboxes_lw, self.from_le)
        MainWindow.setTabOrder(self.from_le, self.to_le)
        MainWindow.setTabOrder(self.to_le, self.subject_le)
        MainWindow.setTabOrder(self.subject_le, self.search_btn)
        MainWindow.setTabOrder(self.search_btn, self.links_text_edit)
        MainWindow.setTabOrder(self.links_text_edit, self.export_txt_btn)
        MainWindow.setTabOrder(self.export_txt_btn, self.export_html_btn)
        MainWindow.setTabOrder(self.export_html_btn, self.disconnect_btn)
        MainWindow.setTabOrder(self.disconnect_btn, self.add_preset_btn)
        MainWindow.setTabOrder(self.add_preset_btn, self.remove_preset_btn)
        MainWindow.setTabOrder(self.remove_preset_btn, self.ssl_cb)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QApplication.translate("MainWindow", "Email Link Extractor", None, QApplication.UnicodeUTF8))
        self.login_gbox.setTitle(QApplication.translate("MainWindow", "  Login", None, QApplication.UnicodeUTF8))
        self.lb_presets.setText(QApplication.translate("MainWindow", "Server Presets", None, QApplication.UnicodeUTF8))
        self.add_preset_btn.setText(QApplication.translate("MainWindow", "+", None, QApplication.UnicodeUTF8))
        self.remove_preset_btn.setText(QApplication.translate("MainWindow", "-", None, QApplication.UnicodeUTF8))
        self.lb_imap_server.setText(QApplication.translate("MainWindow", "IMAP Server", None, QApplication.UnicodeUTF8))
        self.lb_ssl.setText(QApplication.translate("MainWindow", "SSL", None, QApplication.UnicodeUTF8))
        self.ssl_cb.setText(QApplication.translate("MainWindow", "Port : 993", None, QApplication.UnicodeUTF8))
        self.lb_adress.setText(QApplication.translate("MainWindow", "Adress", None, QApplication.UnicodeUTF8))
        self.lb_pass.setText(QApplication.translate("MainWindow", "Password", None, QApplication.UnicodeUTF8))
        self.connect_btn.setText(QApplication.translate("MainWindow", "Connect", None, QApplication.UnicodeUTF8))
        self.lb_select_mailbox.setText(QApplication.translate("MainWindow", "Select Mailbox", None, QApplication.UnicodeUTF8))

        self.search_gbox.setTitle(QApplication.translate("MainWindow", "  Search Parameters", None, QApplication.UnicodeUTF8))
        self.since_date_cb.setText(QApplication.translate("MainWindow", "Since", None, QApplication.UnicodeUTF8))
        self.since_date_edit.setDisplayFormat(QApplication.translate("MainWindow", "dd-MMM-yyyy", None, QApplication.UnicodeUTF8))
        self.before_date_cb.setText(QApplication.translate("MainWindow", "Before", None, QApplication.UnicodeUTF8))
        self.before_date_edit.setDisplayFormat(QApplication.translate("MainWindow", "dd-MMM-yyyy", None, QApplication.UnicodeUTF8))

        self.html_radio.setText(QApplication.translate("MainWindow", "html", None, QApplication.UnicodeUTF8))
        self.text_radio.setText(QApplication.translate("MainWindow", "text", None, QApplication.UnicodeUTF8))
        # self.lb_threads.setText(QApplication.translate("MainWindow", "Threads", None, QApplication.UnicodeUTF8))

        self.lb_from.setText(QApplication.translate("MainWindow", "From", None, QApplication.UnicodeUTF8))
        self.lb_to.setText(QApplication.translate("MainWindow", "To", None, QApplication.UnicodeUTF8))
        self.lb_subject.setText(QApplication.translate("MainWindow", "Subject", None, QApplication.UnicodeUTF8))
        self.search_btn.setText(QApplication.translate("MainWindow", "Search", None, QApplication.UnicodeUTF8))

        self.links_gbox.setTitle(QApplication.translate("MainWindow", "  Links", None, QApplication.UnicodeUTF8))
        self.export_html_btn.setText(QApplication.translate("MainWindow", "Export as HTML", None, QApplication.UnicodeUTF8))
        self.export_txt_btn.setText(QApplication.translate("MainWindow", "Export as txt", None, QApplication.UnicodeUTF8))
        self.log_gbox.setTitle(QApplication.translate("MainWindow", "  Log", None, QApplication.UnicodeUTF8))
        self.disconnect_btn.setText(QApplication.translate("MainWindow", "Disconnect", None, QApplication.UnicodeUTF8))
        self.menu_file.setTitle(QApplication.translate("MainWindow", "File", None, QApplication.UnicodeUTF8))
        self.menu_about.setTitle(QApplication.translate("MainWindow", "About", None, QApplication.UnicodeUTF8))
        self.action_about.setText(QApplication.translate("MainWindow", "About", None, QApplication.UnicodeUTF8))
        self.action_About_Qt.setText(QApplication.translate("MainWindow", "About Qt", None, QApplication.UnicodeUTF8))
        self.action_exit.setText(QApplication.translate("MainWindow", "Exit", None, QApplication.UnicodeUTF8))
        self.action_exit.setShortcut(QApplication.translate("MainWindow", "Ctrl+Q", None, QApplication.UnicodeUTF8))
        self.actionSave.setText(QApplication.translate("MainWindow", "Save", None, QApplication.UnicodeUTF8))
class TwoStepLandmarkWidget(QWidget):
	"""
	TwoStepLandmarkWidget
	"""

	pickedPosition = Signal()

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

		self.textFrame = QTextEdit("<p>Place your mouse over the desired "
			"landmark point. Press 'Space' to shoot a ray through the volume. "
			"Move the volume around and move the mouse to move the locator. "
			"Press 'Space' again to define the final place of the landmark.</p>"
			"<p>You can also use the ray profile to define the landmark's location.</p>")
		self.textFrame.setReadOnly(True)
		self.textFrame.setFrameShape(QFrame.NoFrame)
		self.textFrame.setAutoFillBackground(False)
		self.textFrame.setAttribute(Qt.WA_TranslucentBackground)
		self.textFrame.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
		self.textFrame.setStyleSheet("background: #aaa")

		self.histogramWidget = TrackingHistogramWidget()
		self.histogramWidget.setMinimumHeight(100)
		self.histogramWidget.setVisible(False)

		self.button = QPushButton("Pick current landmark position")
		self.button.clicked.connect(self.applyButtonClicked)
		self.button.setVisible(False)

		layout = QGridLayout()
		layout.setAlignment(Qt.AlignTop)
		layout.setSpacing(0)
		layout.setContentsMargins(0, 0, 0, 0)
		layout.addWidget(self.textFrame)
		layout.addWidget(self.histogramWidget)
		layout.addWidget(self.button)
		self.setLayout(layout)

	def setSamples(self, samples, scope=None):
		self.textFrame.setVisible(False)
		self.histogramWidget.setVisible(True)

		self.histogram = Histogram()
		self.histogram.bins = samples
		
		if scope:
			self.histogram.minY = scope[0]
			self.histogram.maxY = scope[1]
			self.histogram.enabled = True

		self.histogramWidget.setHistogram(self.histogram)
		self.histogramWidget.setAxeMode(left=HistogramWidget.AxeNormal)
		self.histogramWidget.nodeItem.tracking = True
		self.button.setVisible(True)

	@Slot()
	def applyButtonClicked(self):
		self.pickedPosition.emit()

	@Slot()
	def pickedLocation(self, location):
		self.histogramWidget.nodeItem.tracking = False
		self.button.setVisible(False)
Beispiel #13
0
    def __init__(self):

        url = QLineEdit()
        urlLabel = QLabel('Url')
        messages = QTextEdit()
        messagesLabel = QLabel('Messages')
        links = QTableWidget(0, 2)
        linksLabel = QLabel('Links')
        clearMessages = QPushButton('Clear Messages')
        checkIfOnline = QPushButton('Check If Online')
        addSelectedLink = QPushButton('Add Link')
        removeSelectedLink = QPushButton('Remove Selected Link')

        messages.setReadOnly(True)

        links.setHorizontalHeaderLabels(['Url', 'Status'])
        links.horizontalHeader().setResizeMode(QHeaderView.Stretch)
        links.horizontalHeader().setResizeMode(1, QHeaderView.Fixed)

        # set the events

        url.returnPressed.connect(self.select_stream_from_entry)
        links.itemDoubleClicked.connect(self.select_stream_from_link)
        clearMessages.clicked.connect(self.clear_messages)
        checkIfOnline.clicked.connect(self.check_if_online)
        addSelectedLink.clicked.connect(self.add_selected_link)
        removeSelectedLink.clicked.connect(self.remove_selected_link)

        # set the layouts

        mainLayout = QGridLayout()

        # first row
        mainLayout.addWidget(urlLabel, 0, 0, 1, 2)  # spans 2 columns
        mainLayout.addWidget(linksLabel, 0, 2, 1, 3)  # spans 3 columns

        # second row  (links widget occupies 2 rows and 2 columns)
        mainLayout.addWidget(url, 1, 0, 1, 2)  # spans 2 columns
        mainLayout.addWidget(links, 1, 2, 2, 3)  # spans 3 columns

        # third row (messages widget occupies 2 columns)
        mainLayout.addWidget(messages, 2, 0, 1, 2)

        # fourth row
        mainLayout.addWidget(messagesLabel, 3, 0)
        mainLayout.addWidget(clearMessages, 3, 1)
        mainLayout.addWidget(checkIfOnline, 3, 2)
        mainLayout.addWidget(addSelectedLink, 3, 3)
        mainLayout.addWidget(removeSelectedLink, 3, 4)

        window = QWidget()

        window.setLayout(mainLayout)
        window.setWindowTitle('Live Streamer')
        window.resize(700, 350)
        window.show()

        self.url_ui = url
        self.messages_ui = messages
        self.links_ui = links
        self.window_ui = window

        self.links = set()
Beispiel #14
0
class CustomWidget(QtGui.QMainWindow):

    def __init__(self):
        """
        Constructor
        """
        QtGui.QMainWindow.__init__(self)
        self.name = "Custom widget"
        self.central_widget = QtGui.QWidget()
        self.setCentralWidget(self.central_widget)

        # TODO: This is ugly, improve it
        self.iconp = JConfig().icons_path

        self._createLayout()


    def _createGui(self):
        """
        Subclasses must override this
        depending on the elements they want to add
        self._createOutputTree(),
        self._createOutputTable(),
        self._createOutputWindow() and add them to
        the corresponding layouts.
        """
        raise NotImplementedError


    def _createToolBar(self, name):
        """
        Subclasses need to define the
        specific Actions
        """
        self.toolbar = self.addToolBar(name)
        self.toolbar.setMovable(False)


    def _createLayout(self):
        """
        This creates the basic layout:
        Buttons & Outputs
        """

        # Layouts (This is a common disposition)
        main_layout = QtGui.QVBoxLayout()
        self.button_layout = QtGui.QHBoxLayout()
        output_layout = QtGui.QVBoxLayout()

        # You will need to create your buttons
        # and add them to your layout like this:
        # self.button_layout.addWidget(button_1)

        # Output Layout Inner (QSplitter)
        # Add as many widgets as you please
        # They will be ordered vertically and
        # be resizable by the user
        # self.splitter.addWidget(self.table_label)
        # self.splitter.addWidget(...)
        self.splitter = QSplitter(QtCore.Qt.Vertical)

        # Nested layouts
        main_layout.addLayout(self.button_layout)
        output_layout.addWidget(self.splitter)
        main_layout.addLayout(output_layout)
        self.central_widget.setLayout(main_layout)


    def _createOutputWindow(self):
        """
        Some binary analysis commands will output to this.
        """

        self.output_label = QtGui.QLabel('Output')

        self.output_window = QTextEdit()
        self.output_window.setFontPointSize(10)
        self.output_window.setReadOnly(True)
        # Save it for later use
        self.output_window.original_textcolor = self.output_window.textColor()


    def _createOutputTable(self):
        """
        A vanilla QTableWidget. Callbacks modify
        its properties, like number of columns, etc.
        """
        self.table_label = QtGui.QLabel('Table Output')

        self.table = QTableWidget()
        self.table.setColumnCount(3)
        self.table.setColumnWidth(0, 100)
        self.table.setColumnWidth(1, 300)
        self.table.setColumnWidth(2, 300)

        self.table.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)

        # Connect signals to slots
        self.table.customContextMenuRequested.connect(self._tablePopup)
        self.table.horizontalHeader().sectionDoubleClicked.connect(self._tableHeaderDoubleClicked)
        self.table.cellDoubleClicked.connect(self._tableCellDoubleClicked)


    def _createOutputTree(self):
        """
        A QtreeWidget. Initially used to display those pesky
        dword comparison to immediate values.
        """
        self.tree_label = QtGui.QLabel('Tree Output')

        self.tree = QTreeWidget()
        self.tree.setColumnCount(3)
        self.tree.setColumnWidth(0, 150)
        self.tree.setColumnWidth(1, 150)
        self.tree.setColumnWidth(2, 50)

        # Connect signals to slots
        self.tree.itemDoubleClicked.connect(self._treeElementDoubleClicked)



    #################################################################
    # GUI Callbacks
    #################################################################
    def _console_output(self, s = "", err = False):
        """
        Convenience wrapper
        """
        if err:
            # Error message
            err_color = QColor('red')
            self.output_window.setTextColor(err_color)
            self.output_window.append(s)
            # restore original color
            self.output_window.setTextColor(self.output_window.original_textcolor)

        else:
            self.output_window.append(s)


    def _tableCellDoubleClicked(self, row, col):
        """
        Most of the info displayed in QTableWidgets represent addresses.
        Default action: try to jump to it.
        """
        it = self.table.item(row, col).text()

        try:
            addr = int(it, 16)
            jump_to_address(addr)

        except ValueError:
            self._console_output("[!] That does not look like an address...", err = True)
            return


    def _tablePopup(self, pos):
        """
        Popup menu activated clicking the secondary
        button on the table
        """
        menu = QtGui.QMenu()

        # Add menu entries
        delRow = menu.addAction(QIcon(self.iconp + "close.png"), "Delete Row")
        selItem = menu.addAction(QIcon(self.iconp + "bookmark.png"), "Mark entry")
        menu.addSeparator()
        origFunc = menu.addAction(QIcon(self.iconp + "lightning.png"), "Select origin function")
        destFunc = menu.addAction(QIcon(self.iconp + "flag.png"), "Select destination function")

        # Get entry clicked
        action = menu.exec_(self.mapToGlobal(pos))

        # Dispatch :)
        if action == delRow:
            self.table.removeRow(self.table.currentRow())

        elif action == selItem:
            self.table.currentItem().setBackground(QtGui.QColor('red'))

        elif action == origFunc:
            try:
                addr = self.table.currentItem().text()
                InfoUI.function_orig_ea = int(addr, 16)

            except:
                self._console_output("This does not look like an address...", err = True)

        elif action == destFunc:
            try:
                addr = self.table.currentItem().text()
                InfoUI.function_dest_ea = int(addr, 16)

            except:
                self._console_output("This does not look like an address...", err = True)


    def _tableHeaderDoubleClicked(self, index):
        """
        Used to sort the contents
        """
        self.table.sortItems(index, order = QtCore.Qt.AscendingOrder)


    def _treeElementDoubleClicked(self, item, column):
        """
        QTreeWidgetElement callback. Basically it jumps to
        the selected address in IDA disassembly window.
        """
        try:
            # Only interested in addresses
            addr_int = int(item.text(column), 16)
            jump_to_address(addr_int)
            # Paint some color
            item.setBackground(column, QtGui.QColor('green'))

        except:
            self._console_output("[!] That does not look like an address...", err = True)
Beispiel #15
0
    def __init__( self ):

        url = QLineEdit()
        quality = QLineEdit()
        urlLabel = QLabel( 'Url' )
        qualityLabel = QLabel( 'Quality' )
        messages = QTextEdit()
        messagesLabel = QLabel( 'Messages' )
        links = QTableWidget( 0, 2 )
        linksLabel = QLabel( 'Links' )
        clearMessages = QPushButton( 'Clear Messages' )
        checkIfOnline = QPushButton( 'Check If Online' )
        addSelectedLink = QPushButton( 'Add Link' )
        removeSelectedLink = QPushButton( 'Remove Selected Link' )

        messages.setReadOnly( True )

        links.setHorizontalHeaderLabels( [ 'Url', 'Status' ] )
        links.horizontalHeader().setResizeMode( QHeaderView.Stretch )
        links.horizontalHeader().setResizeMode( 1, QHeaderView.Fixed )

            # set the events

        url.returnPressed.connect( self.select_stream_from_entry )
        quality.returnPressed.connect( self.select_stream_from_entry )
        links.itemDoubleClicked.connect( self.select_stream_from_link )
        clearMessages.clicked.connect( self.clear_messages )
        checkIfOnline.clicked.connect( self.check_if_online )
        addSelectedLink.clicked.connect( self.add_selected_link )
        removeSelectedLink.clicked.connect( self.remove_selected_link )

        #set shortcut
        checkIfOnline.setShortcut(QKeySequence(Qt.Key_F5))

            # set the layouts

        mainLayout = QGridLayout()

            # first row
        mainLayout.addWidget( urlLabel, 0, 0, 1, 1 )    # spans 1 column
        mainLayout.addWidget( qualityLabel, 0, 1, 1, 1 )# spans 1 column
        mainLayout.addWidget( linksLabel, 0, 2, 1, 3 )  # spans 3 columns

            # second row  (links widget occupies 2 rows and 2 columns)
        mainLayout.addWidget( url, 1, 0, 1, 1 )         # spans 1 column
        mainLayout.addWidget( quality, 1, 1, 1, 1 )     # spans 1 column
        mainLayout.addWidget( links, 1, 2, 2, 3 )   # spans 3 columns

            # third row (messages widget occupies 2 columns)
        mainLayout.addWidget( messages, 2, 0, 1, 2 )

            # fourth row
        mainLayout.addWidget( messagesLabel, 3, 0 )
        mainLayout.addWidget( clearMessages, 3, 1 )
        mainLayout.addWidget( checkIfOnline, 3, 2 )
        mainLayout.addWidget( addSelectedLink, 3, 3 )
        mainLayout.addWidget( removeSelectedLink, 3, 4 )


        window = QWidget()

        window.setLayout( mainLayout )
        window.setWindowTitle( 'Live Streamer' )
        window.resize( 700, 350 )
        window.show()

        self.url_ui = url
        self.quality_ui = quality
        self.messages_ui = messages
        self.links_ui = links
        self.window_ui = window

        self.links = set()

        self.data_file = os.path.join(os.path.expanduser("~"), ".config", "livestreamer-ui", "data.txt")
        folder=os.path.dirname(self.data_file)
        if not os.path.exists(folder):
                os.makedirs(folder)
Beispiel #16
0
class Dialog(QWidget):

    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)
        self.setupUI()
        self.setupConnection()
        self.threadPool = []
        self.totalUids = 0
        self.finishedThreadNum = 0
        self.realThreadNum = 0
        self.excel = Excel()
        #self.initSearchDb()

    def setupUI(self):

        self.pushButton = QPushButton(u"Search", self)
        #self.testButton = QPushButton(u"Test", self)
        self.lineEdit = QLineEdit(self)
        self.textEdit = QTextEdit(self)
        self.comboBox = QComboBox(self)
        self.label = QLabel(u"DB:", self)
        self.progressBar = QProgressBar(self)
        self.progressBar.setRange(0,1)
        
        self.textEdit.setReadOnly(True)

        self.layout = QVBoxLayout()
        self.topLayout = QHBoxLayout()
        
        self.topLayout.addWidget(self.label)
        self.topLayout.addWidget(self.comboBox)
        self.topLayout.addWidget(self.lineEdit)
        self.topLayout.addWidget(self.pushButton)
        #self.topLayout.addWidget(self.testButton)

        #self.testButton.clicked.connect(self.onTestButtonClicked)

        self.layout.addLayout(self.topLayout)
        self.layout.addWidget(self.textEdit)
        self.layout.addWidget(self.progressBar)

        self.setLayout(self.layout)

        self.resize(600, 700)
        self.setWindowTitle(u"Search Data for NCBI")

    def setupConnection(self):
        self.pushButton.clicked.connect(self.onButtonClicked)

    def onButtonClicked(self):
        if not self.lineEdit.text() or not self.comboBox.count():
            QtGui.QMessageBox.information(self, u"Warning", u"Please Set the Search Field")
            return
        # disable button
        self.pushButton.setDisabled(True)
        dbName = self.comboBox.currentText()
        fieldName = self.lineEdit.text()
        self.log("Start searching db: %s and field: %s" % (dbName, fieldName))
        # add use history to add all uids to the history server
        handle = self.entrez.esearch(db=dbName, term=fieldName, usehistory='y')
        record = self.entrez.read(handle)
        self.log("All result count %s" % record['Count'])
        self.totalUids = int(record['Count'])
        # to get onnly data less than the MAX_COUNT
        if self.totalUids > MAX_COUNT:
            ret = QtGui.QMessageBox.question(
                    self,
                    u'Warning',
                    u'result count %s is too large, will only get the %s result \
                            continue?' % (self.totalUids, MAX_COUNT),
                            QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel
                            )
            if ret == QtGui.QMessageBox.Ok:
                self.totalUids = MAX_COUNT
            else:
                return
        #handle = self.entrez.efetch(db=dbName, id=record['IdList'], rettype='gb')
        self.finishedThreadNum = 0
        WebEnv = record['WebEnv']
        QueryKey = record['QueryKey']
        global FINISHED_COUNT
        FINISHED_COUNT = 0
        self.progressBar.setValue(0)
        self.progressBar.setMaximum(self.totalUids)
        if self.totalUids / RET_MAX_SUMMARY >= MAX_THREAD:
            self.realThreadNum = MAX_THREAD
            each_count = self.totalUids/MAX_THREAD
            startIndex = 0
            for i in range(MAX_THREAD - 1):
                thread = MyThread(startIndex, each_count, dbName, fieldName, WebEnv, QueryKey)
                thread.finished.connect(self.onThreadFinished)
                thread.finishedCountChanged.connect(self.onFinishedCountChange)
                thread.start()
                self.threadPool.append(thread)
                startIndex = startIndex + each_count
            thread = MyThread(startIndex, (self.totalUids-startIndex+1), dbName, fieldName, WebEnv, QueryKey)
            thread.finished.connect(self.onThreadFinished)
            thread.finishedCountChanged.connect(self.onFinishedCountChange)
            self.threadPool.append(thread)
            thread.start()
        else:
            if self.totalUids == RET_MAX_SUMMARY:
                self.realThreadNum = 1
            else:
                self.realThreadNum = self.totalUids/RET_MAX_SUMMARY + 1
            startIndex = 0
            for i in range(self.realThreadNum):
                thread = MyThread(startIndex, RET_MAX_SUMMARY, dbName, fieldName, WebEnv, QueryKey)
                thread.finished.connect(self.onThreadFinished)
                thread.finishedCountChanged.connect(self.onFinishedCountChange)
                self.threadPool.append(thread)
                thread.start()
                startIndex = startIndex + RET_MAX_SUMMARY
        self.log("thread num: %s" % self.realThreadNum)
        self.log('reading data')
        self.filename = '%s_%s_output.xls' % (dbName, fieldName)
        self.excel.setFilename(self.filename)

    def log(self, context):
        self.textEdit.append(context)

    def initSearchDb(self):
        self.entrez = Entrez 
        self.entrez.email = email
        self.log("Connect to NCBI")
        try:
            handle = self.entrez.einfo()
        except:
            QtGui.QMessageBox.warning(self, u"Error", u"Error Connect the WebSite")
            self.close()
        record = self.entrez.read(handle)
        self.log("Get NCBI DataBases:")
        for name in record['DbList']:
            self.log('DBName:\t%s' % name)
        self.comboBox.addItems(record['DbList'])

    def onThreadFinished(self):
        self.finishedThreadNum = self.finishedThreadNum + 1
        self.log('finished thread %s ' % self.finishedThreadNum)
        if(self.finishedThreadNum == self.realThreadNum):
            global all_output
            heads = all_output[0][0].keys()
            self.excel.setHead(heads)
            for values in all_output:
                for value in values:
                    self.excel.addValues(value)
            self.excel.save()
            self.progressBar.setValue(int(self.totalUids))
            # clear all thread
            self.threadPool = []
            all_output = []
            self.excel.clearValues()
            self.pushButton.setDisabled(False)
            self.log("output to file: %s" % self.filename)

    def onFinishedCountChange(self, num):
        self.progressBar.setValue(num)

    def onTestButtonClicked(self):
        self.finishedThreadNum = 0
        self.realThreadNum = 1
        self.thread = MyThread(0, 10,"abd","123")
        self.thread.finished.connect(self.onThreadFinished)
        self.thread.startIndex()
Beispiel #17
0
class CCParsedTab(QWidget):
    def __init__(self, parser_result):
        QWidget.__init__(self)
        self._parser_result = parser_result

        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSizeConstraint(QHBoxLayout.SetMinimumSize)

        self.table_widget = QTableWidget()
        self.table_widget.setSelectionMode(QAbstractItemView.NoSelection)
        self.table_widget.setRowCount(2)
        self.table_widget.setColumnCount(2)
        self.table_widget.horizontalHeader().setResizeMode(QHeaderView.Stretch)
        self.table_widget.setHorizontalHeaderLabels(["Dimension", "Choice"])
        self.table_widget.verticalHeader().setVisible(False)
        self.table_widget.verticalHeader().setResizeMode(QHeaderView.Fixed)
        self.table_widget.verticalHeader().setDefaultSectionSize(20)
        sp_table = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sp_table.setHorizontalStretch(1)
        self.table_widget.setSizePolicy(sp_table)

        layout.addWidget(self.table_widget)

        self.text_widget = QTextEdit()
        sp_text = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sp_text.setHorizontalStretch(4)
        self.text_widget.setReadOnly(True)
        self.text_widget.setSizePolicy(sp_text)
        self.text_widget.setStyleSheet('font: 9pt "Courier";')
        self.text_widget.setText(self._parser_result.get_text())

        layout.addWidget(self.text_widget)

        self.setLayout(layout)

        self._fill_table()

    def _fill_table(self):
        colors = ["yellow", "orange", "green", "red"]

        dimensions = self._parser_result.get_dimensions()
        row = 0
        for dimension in dimensions:
            dimension_name = QLabel(dimension[0])
            dimension_name.setStyleSheet("background: %s" % colors[row % len(colors)])
            self.table_widget.setCellWidget(row, 0, dimension_name)
            choices_widget = QComboBox()
            choices = dimension[1]
            choices.insert(0, "No choice")
            choices_widget.addItems(choices)
            choices_widget.setStyleSheet("background: white")
            choices_widget.setStyleSheet("border: none")
            choices_widget.currentIndexChanged.connect(self.on_choice_change)
            self.table_widget.setCellWidget(row, 1, choices_widget)
            row += 1

    @Slot()
    def on_choice_change(self):
        text = self._parser_result.get_text()
        for row in range(self.table_widget.rowCount()):
            label = self.table_widget.cellWidget(row, 0)
            choices = self.table_widget.cellWidget(row, 1)
            if choices.currentIndex() == 0:
                continue
            regex = self._build_regex(label.text(), choices.count() - 1)
            pattern = re.compile(regex)
            matches = pattern.search(text)
            for match in matches.groups():
                results = re.search("<(.+)>", match)
                variants = [s.strip() for s in results.groups()[0].split(",")]
                text = text.replace(match, variants[choices.currentIndex() - 1])
        self.text_widget.setText(text)

    @staticmethod
    def _build_regex(dim, count):
        regex = "(" + dim + "<"
        for i in range(count):
            regex += ".+,[ ]?"
        regex = regex[:-5]
        regex += ">)"
        return regex
Beispiel #18
0
class CustomWidget(QtGui.QMainWindow):
    def __init__(self):
        """
        Constructor
        """
        QtGui.QMainWindow.__init__(self)
        self.name = "Custom widget"
        self.central_widget = QtGui.QWidget()
        self.setCentralWidget(self.central_widget)

        # TODO: This is ugly, improve it
        self.iconp = JConfig().icons_path

        self._createLayout()

    def _createGui(self):
        """
        Subclasses must override this
        depending on the elements they want to add
        self._createOutputTree(),
        self._createOutputTable(),
        self._createOutputWindow() and add them to
        the corresponding layouts.
        """
        raise NotImplementedError

    def _createToolBar(self, name):
        """
        Subclasses need to define the
        specific Actions
        """
        self.toolbar = self.addToolBar(name)
        self.toolbar.setMovable(False)

    def _createLayout(self):
        """
        This creates the basic layout:
        Buttons & Outputs
        """

        # Layouts (This is a common disposition)
        main_layout = QtGui.QVBoxLayout()
        self.button_layout = QtGui.QHBoxLayout()
        output_layout = QtGui.QVBoxLayout()

        # You will need to create your buttons
        # and add them to your layout like this:
        # self.button_layout.addWidget(button_1)

        # Output Layout Inner (QSplitter)
        # Add as many widgets as you please
        # They will be ordered vertically and
        # be resizable by the user
        # self.splitter.addWidget(self.table_label)
        # self.splitter.addWidget(...)
        self.splitter = QSplitter(QtCore.Qt.Vertical)

        # Nested layouts
        main_layout.addLayout(self.button_layout)
        output_layout.addWidget(self.splitter)
        main_layout.addLayout(output_layout)
        self.central_widget.setLayout(main_layout)

    def _createOutputWindow(self):
        """
        Some binary analysis commands will output to this.
        """

        self.output_label = QtGui.QLabel('Output')

        self.output_window = QTextEdit()
        self.output_window.setFontPointSize(10)
        self.output_window.setReadOnly(True)
        # Save it for later use
        self.output_window.original_textcolor = self.output_window.textColor()

    def _createOutputTable(self):
        """
        A vanilla QTableWidget. Callbacks modify
        its properties, like number of columns, etc.
        """
        self.table_label = QtGui.QLabel('Table Output')

        self.table = QTableWidget()
        self.table.setColumnCount(3)
        self.table.setColumnWidth(0, 100)
        self.table.setColumnWidth(1, 300)
        self.table.setColumnWidth(2, 300)

        self.table.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)

        # Connect signals to slots
        self.table.customContextMenuRequested.connect(self._tablePopup)
        self.table.horizontalHeader().sectionDoubleClicked.connect(
            self._tableHeaderDoubleClicked)
        self.table.cellDoubleClicked.connect(self._tableCellDoubleClicked)

    def _createOutputTree(self):
        """
        A QtreeWidget. Initially used to display those pesky
        dword comparison to immediate values.
        """
        self.tree_label = QtGui.QLabel('Tree Output')

        self.tree = QTreeWidget()
        self.tree.setColumnCount(3)
        self.tree.setColumnWidth(0, 150)
        self.tree.setColumnWidth(1, 150)
        self.tree.setColumnWidth(2, 50)

        # Connect signals to slots
        self.tree.itemDoubleClicked.connect(self._treeElementDoubleClicked)

    #################################################################
    # GUI Callbacks
    #################################################################
    def _console_output(self, s="", err=False):
        """
        Convenience wrapper
        """
        if err:
            # Error message
            err_color = QColor('red')
            self.output_window.setTextColor(err_color)
            self.output_window.append(s)
            # restore original color
            self.output_window.setTextColor(
                self.output_window.original_textcolor)

        else:
            self.output_window.append(s)

    def _tableCellDoubleClicked(self, row, col):
        """
        Most of the info displayed in QTableWidgets represent addresses.
        Default action: try to jump to it.
        """
        it = self.table.item(row, col).text()

        try:
            addr = int(it, 16)
            jump_to_address(addr)

        except ValueError:
            self._console_output("[!] That does not look like an address...",
                                 err=True)
            return

    def _tablePopup(self, pos):
        """
        Popup menu activated clicking the secondary
        button on the table
        """
        menu = QtGui.QMenu()

        # Add menu entries
        delRow = menu.addAction(QIcon(self.iconp + "close.png"), "Delete Row")
        selItem = menu.addAction(QIcon(self.iconp + "bookmark.png"),
                                 "Mark entry")
        menu.addSeparator()
        origFunc = menu.addAction(QIcon(self.iconp + "lightning.png"),
                                  "Select origin function")
        destFunc = menu.addAction(QIcon(self.iconp + "flag.png"),
                                  "Select destination function")

        # Get entry clicked
        action = menu.exec_(self.mapToGlobal(pos))

        # Dispatch :)
        if action == delRow:
            self.table.removeRow(self.table.currentRow())

        elif action == selItem:
            self.table.currentItem().setBackground(QtGui.QColor('red'))

        elif action == origFunc:
            try:
                addr = self.table.currentItem().text()
                InfoUI.function_orig_ea = int(addr, 16)

            except:
                self._console_output("This does not look like an address...",
                                     err=True)

        elif action == destFunc:
            try:
                addr = self.table.currentItem().text()
                InfoUI.function_dest_ea = int(addr, 16)

            except:
                self._console_output("This does not look like an address...",
                                     err=True)

    def _tableHeaderDoubleClicked(self, index):
        """
        Used to sort the contents
        """
        self.table.sortItems(index, order=QtCore.Qt.AscendingOrder)

    def _treeElementDoubleClicked(self, item, column):
        """
        QTreeWidgetElement callback. Basically it jumps to
        the selected address in IDA disassembly window.
        """
        try:
            # Only interested in addresses
            addr_int = int(item.text(column), 16)
            jump_to_address(addr_int)
            # Paint some color
            item.setBackground(column, QtGui.QColor('green'))

        except:
            self._console_output("[!] That does not look like an address...",
                                 err=True)
Beispiel #19
0
    def __init__(self):

        url = QLineEdit()
        quality = QLineEdit()
        urlLabel = QLabel('Url')
        qualityLabel = QLabel('Quality')
        messages = QTextEdit()
        messagesLabel = QLabel('Messages')
        links = QTableWidget(0, 2)
        linksLabel = QLabel('Links')
        clearMessages = QPushButton('Clear Messages')
        checkIfOnline = QPushButton('Check If Online')
        addSelectedLink = QPushButton('Add Link')
        removeSelectedLink = QPushButton('Remove Selected Link')

        messages.setReadOnly(True)

        links.setHorizontalHeaderLabels(['Url', 'Status'])
        links.horizontalHeader().setResizeMode(QHeaderView.Stretch)
        links.horizontalHeader().setResizeMode(1, QHeaderView.Fixed)

        # set the events

        url.returnPressed.connect(self.select_stream_from_entry)
        quality.returnPressed.connect(self.select_stream_from_entry)
        links.itemDoubleClicked.connect(self.select_stream_from_link)
        clearMessages.clicked.connect(self.clear_messages)
        checkIfOnline.clicked.connect(self.check_if_online)
        addSelectedLink.clicked.connect(self.add_selected_link)
        removeSelectedLink.clicked.connect(self.remove_selected_link)

        #set shortcut
        checkIfOnline.setShortcut(QKeySequence(Qt.Key_F5))

        # set the layouts

        mainLayout = QGridLayout()

        # first row
        mainLayout.addWidget(urlLabel, 0, 0, 1, 1)  # spans 1 column
        mainLayout.addWidget(qualityLabel, 0, 1, 1, 1)  # spans 1 column
        mainLayout.addWidget(linksLabel, 0, 2, 1, 3)  # spans 3 columns

        # second row  (links widget occupies 2 rows and 2 columns)
        mainLayout.addWidget(url, 1, 0, 1, 1)  # spans 1 column
        mainLayout.addWidget(quality, 1, 1, 1, 1)  # spans 1 column
        mainLayout.addWidget(links, 1, 2, 2, 3)  # spans 3 columns

        # third row (messages widget occupies 2 columns)
        mainLayout.addWidget(messages, 2, 0, 1, 2)

        # fourth row
        mainLayout.addWidget(messagesLabel, 3, 0)
        mainLayout.addWidget(clearMessages, 3, 1)
        mainLayout.addWidget(checkIfOnline, 3, 2)
        mainLayout.addWidget(addSelectedLink, 3, 3)
        mainLayout.addWidget(removeSelectedLink, 3, 4)

        window = QWidget()

        window.setLayout(mainLayout)
        window.setWindowTitle('Live Streamer')
        window.resize(700, 350)
        window.show()

        self.url_ui = url
        self.quality_ui = quality
        self.messages_ui = messages
        self.links_ui = links
        self.window_ui = window

        self.links = set()

        self.data_file = os.path.join(os.path.expanduser("~"), ".config",
                                      "livestreamer-ui", "data.txt")
        folder = os.path.dirname(self.data_file)
        if not os.path.exists(folder):
            os.makedirs(folder)
Beispiel #20
0
class MainWindow(QMainWindow):
    def __init__(self):

        # QMainWindow.__init__(self)
        super().__init__()      # use super() to avoid explicit dependency on the base class name
                                # Note: must not pass the self reference to __init__ in this case!
        self.resize(800, 600)

        # Create the main content widget
        mainWidget = QWidget(self)
        self.setCentralWidget(mainWidget)

        # Create a text component at the top area of the main widget
        self.output = QTextEdit(mainWidget)
        self.output.setReadOnly(True)
        self.output.setLineWrapMode(QTextEdit.NoWrap);

        # set the font
        font = self.output.font()
        font.setFamily("Courier")
        font.setPointSize(10)
        self.output.setFont(font)

        # Set the background color
        # self.output.setTextBackgroundColor(Qt.red) # Only sets the background color for the text itself, not for the whole widget
        pal = self.output.palette()
        pal.setColor(QPalette.Base, Qt.black)
        self.output.setPalette(pal)

        mainLayout = QVBoxLayout(mainWidget)
        mainLayout.addWidget(self.output)

        # Create buttons in a grid layout below the top area
        buttonWidget = QWidget(mainWidget)
        self.buttonLayout = QGridLayout(buttonWidget)
        mainLayout.addWidget(buttonWidget)

        # Add some buttons to execute python code
        self.row = 0
        self.column = 0
        self.addButton("Clear console", lambda : self.output.clear())
        self.newRow()

        # Add buttons for all the examples - attention: do not make "examples"
        # a local variable - otherwise, the Examples object would be destroyed
        # at the end of __init__ !!!
        self.examples = samplePackage.SampleModule.Examples(self)
        for example in self.examples.getExamples():
            if example is None:
                self.newRow()
            else:
                self.addButton(example.label, example.function)

        # In a Python program, sys.excepthook is called just before the program exits.
        # So we can catch all fatal, uncaught exceptions and log them.
        # NOTE: we must be sure not to set the excepthook BEFORE we an actually
        # log something!! 
        sys.excepthook = self.logException

        self.writelnColor(Qt.magenta, 
                          "Python version: {0}.{1}.{2} ({3})".format(
                              sys.version_info[0], 
                              sys.version_info[1], 
                              sys.version_info[2], 
                              sys.version_info[3]))
        self.writelnColor(Qt.magenta, 
                          "Qt version    : {0}".format(qVersion()))


    def logException(self, exctype, value, tb):
        self.writelnColor(Qt.red, 
                          ("\nFATAL ERROR: Uncaught exception\n"
                           "  {}: {}\n"
                           "{}\n".format(exctype.__name__, value, ''.join(traceback.format_tb(tb)))) )


    def addButton(self, label, function):
        theButton = QPushButton(label)
        theButton.clicked.connect(function)
        self.buttonLayout.addWidget(theButton, self.row, self.column)
        self.column += 1


    def newRow(self):
        self.row += 1
        self.column = 0


    def writeColor(self, color, *text):
        theText =  ' '.join(map(str, text))
        self.output.setTextColor(color)

        # Note: append() adds a new paragraph!
        #self.output.append(theText)
        self.output.textCursor().movePosition(QTextCursor.End)
        self.output.insertPlainText(theText)

        # scroll console window to bottom        
        sb = self.output.verticalScrollBar()
        sb.setValue(sb.maximum())


    def write(self, *text):
        self.writeColor(Qt.green, *text)


    def writelnColor(self, color, *text):
        self.writeColor(color, *text)
        self.write('\n')


    def writeln(self, *text):
        self.writelnColor(Qt.green, *text)
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):

        lbMinWidth = 65
        # leMinWidth = 200

        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(400, 310)

        # self.centralwidget = QWidget(MainWindow)
        self.mainSplitter = QSplitter(Qt.Horizontal, MainWindow)
        self.mainSplitter.setObjectName("centralwidget")
        self.mainSplitter.setProperty("childrenCollapsible", False)
        MainWindow.setCentralWidget(self.mainSplitter)

        self.leftSplitter = QSplitter(Qt.Vertical, self.mainSplitter)
        self.leftSplitter.setProperty("childrenCollapsible", False)
        ##### login_gbox
        self.login_gbox = QGroupBox(self.leftSplitter)
        self.login_gbox.setFlat(True)
        self.login_gbox.setObjectName("login_gbox")

        login_gbox_layout = QVBoxLayout(self.login_gbox)
        login_gbox_csf_layout = QHBoxLayout()
        login_gbox_account_layout = QHBoxLayout()
        login_gbox_connect_layout = QHBoxLayout()
        login_gbox_layout.addLayout(login_gbox_csf_layout)
        login_gbox_layout.addLayout(login_gbox_account_layout)
        login_gbox_layout.addLayout(login_gbox_connect_layout)

        self.lb_client_secrets_file_path = QLabel(self.login_gbox)
        self.lb_client_secrets_file_path.setObjectName("lb_client_secrets_file_path")
        self.lb_client_secrets_file_path.setMinimumWidth(lbMinWidth)

        self.client_secrets_file_path_le = QLineEdit(self.login_gbox)
        self.client_secrets_file_path_le.setObjectName("client_secrets_file_path_le")

        self.client_secret_file_path_tBtn = QToolButton(self.login_gbox)
        self.client_secret_file_path_tBtn.setObjectName("client_secret_file_path_tBtn")

        login_gbox_csf_layout.addWidget(self.lb_client_secrets_file_path)
        login_gbox_csf_layout.addWidget(self.client_secrets_file_path_le)
        login_gbox_csf_layout.addWidget(self.client_secret_file_path_tBtn)

        self.lb_account = QLabel(self.login_gbox)
        self.lb_account.setMaximumWidth(lbMinWidth)
        self.lb_account.setObjectName("lb_account")

        self.remove_account_btn = QToolButton(self.login_gbox)
        self.remove_account_btn.setObjectName("remove_account_btn")
        self.remove_account_btn.setMinimumWidth(20)
        self.remove_account_btn.setEnabled(False)

        self.add_account_btn = QToolButton(self.login_gbox)
        self.add_account_btn.setObjectName("add_account_btn")
        self.add_account_btn.setMinimumWidth(20)

        self.accounts_cb = QComboBox(self.login_gbox)
        self.accounts_cb.setObjectName("accounts_cb")

        login_gbox_account_layout.addWidget(self.lb_account)
        login_gbox_account_layout.addWidget(self.remove_account_btn)
        login_gbox_account_layout.addWidget(self.add_account_btn)
        login_gbox_account_layout.addWidget(self.accounts_cb)

        self.lb_decryption_key = QLabel(self.login_gbox)
        self.lb_decryption_key.setObjectName("lb_decryption_key")
        self.lb_decryption_key.setMinimumWidth(lbMinWidth)
        self.lb_decryption_key.hide()

        self.decryption_key_le = QLineEdit(self.login_gbox)
        self.decryption_key_le.setEchoMode(QLineEdit.Password)
        self.decryption_key_le.setObjectName("decryption_key_le")
        self.decryption_key_le.hide()

        self.connect_btn = QPushButton(self.login_gbox)
        self.connect_btn.setEnabled(False)
        self.connect_btn.setObjectName("connect_btn")

        login_gbox_connect_layout.addWidget(self.lb_decryption_key)
        login_gbox_connect_layout.addWidget(self.decryption_key_le)
        login_gbox_connect_layout.addWidget(self.connect_btn)

        #### search_gbox
        self.search_gbox = QGroupBox(self.leftSplitter)
        self.search_gbox.setFlat(True)
        self.search_gbox.setObjectName("search_gbox")
        self.search_gbox.hide()

        search_gbox_layout = QVBoxLayout(self.search_gbox)
        search_gbox_mailbox_layout = QVBoxLayout()
        search_gbox_date_layout = QHBoxLayout()
        search_gbox_from_layout = QHBoxLayout()
        search_gbox_to_layout = QHBoxLayout()
        search_gbox_subject_layout = QHBoxLayout()
        search_gbox_threads_layout = QHBoxLayout()
        search_gbox_paramaters_layout = QHBoxLayout()

        search_gbox_layout.addLayout(search_gbox_mailbox_layout)
        search_gbox_layout.addLayout(search_gbox_date_layout)
        search_gbox_layout.addLayout(search_gbox_from_layout)
        search_gbox_layout.addLayout(search_gbox_to_layout)
        search_gbox_layout.addLayout(search_gbox_subject_layout)
        search_gbox_layout.addLayout(search_gbox_threads_layout)
        search_gbox_layout.addLayout(search_gbox_paramaters_layout)

        self.lb_select_mailbox = QLabel(self.search_gbox)
        self.lb_select_mailbox.setObjectName("lb_select_mailbox")
        self.mailboxes_lw = QListWidget(self.search_gbox)
        self.mailboxes_lw.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.mailboxes_lw.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.mailboxes_lw.setObjectName("mailboxes_lw")
        search_gbox_mailbox_layout.addWidget(self.lb_select_mailbox)
        search_gbox_mailbox_layout.addWidget(self.mailboxes_lw)

        self.after_date_cb = QCheckBox(self.search_gbox)
        self.after_date_cb.setObjectName("after_date_cb")
        self.after_date_cb.setMinimumWidth(lbMinWidth)
        self.after_date_cb.setMaximumWidth(lbMinWidth)
        self.after_date_edit = QDateEdit(self.search_gbox)
        self.after_date_edit.setCalendarPopup(True)
        self.after_date_edit.setObjectName("after_date_edit")
        self.after_date_edit.setDate(QDate.currentDate().addDays(-365))
        self.after_date_edit.setMaximumDate(QDate.currentDate())
        self.after_date_edit.setEnabled(False)
        self.before_date_cb = QCheckBox(self.search_gbox)
        self.before_date_cb.setObjectName("before_date_cb")
        self.before_date_cb.setMinimumWidth(70)
        self.before_date_cb.setMaximumWidth(70)
        self.before_date_edit = QDateEdit(self.search_gbox)
        self.before_date_edit.setCalendarPopup(True)
        self.before_date_edit.setObjectName("before_date_edit")
        self.before_date_edit.setDate(QDate.currentDate())
        self.before_date_edit.setMaximumDate(QDate.currentDate())
        self.before_date_edit.setEnabled(False)
        search_gbox_date_layout.addWidget(self.after_date_cb)
        search_gbox_date_layout.addWidget(self.after_date_edit)
        search_gbox_date_layout.addWidget(self.before_date_cb)
        search_gbox_date_layout.addWidget(self.before_date_edit)

        self.lb_from = QLabel(self.search_gbox)
        self.lb_from.setObjectName("lb_from")
        self.lb_from.setMinimumWidth(lbMinWidth)
        self.from_le = QLineEdit(self.search_gbox)
        self.from_le.setObjectName("from_le")
        search_gbox_from_layout.addWidget(self.lb_from)
        search_gbox_from_layout.addWidget(self.from_le)

        self.lb_to = QLabel(self.search_gbox)
        self.lb_to.setObjectName("lb_to")
        self.lb_to.setMinimumWidth(lbMinWidth)
        self.to_le = QLineEdit(self.search_gbox)
        self.to_le.setObjectName("to_le")
        search_gbox_to_layout.addWidget(self.lb_to)
        search_gbox_to_layout.addWidget(self.to_le)

        self.lb_subject = QLabel(self.search_gbox)
        self.lb_subject.setObjectName("lb_subject")
        self.lb_subject.setMinimumWidth(lbMinWidth)
        self.subject_le = QLineEdit(self.search_gbox)
        self.subject_le.setObjectName("subject_le")
        search_gbox_subject_layout.addWidget(self.lb_subject)
        search_gbox_subject_layout.addWidget(self.subject_le)

        self.lb_threads = QLabel(self.search_gbox)
        self.lb_threads.setObjectName("lb_threads")
        self.lb_threads.setMaximumWidth(lbMinWidth)
        self.thread_count_sb = QSpinBox(self.search_gbox)
        self.thread_count_sb.setMinimum(1)
        self.thread_count_sb.setMaximum(10)
        self.thread_count_sb.setObjectName("thread_count_sb")
        self.html_radio = QRadioButton(self.search_gbox)
        self.html_radio.setObjectName("html_radio")
        self.text_radio = QRadioButton(self.search_gbox)
        self.text_radio.setObjectName("text_radio")
        self.extactTypeButtonGroup = QButtonGroup(self)
        self.extactTypeButtonGroup.addButton(self.html_radio)
        self.extactTypeButtonGroup.addButton(self.text_radio)
        self.html_radio.setChecked(True)
        self.search_btn = QPushButton(self.search_gbox)
        self.search_btn.setObjectName("search_btn")
        search_gbox_threads_layout.addWidget(self.lb_threads)
        search_gbox_threads_layout.addWidget(self.thread_count_sb)
        search_gbox_threads_layout.addWidget(self.html_radio)
        search_gbox_threads_layout.addWidget(self.text_radio)
        search_gbox_threads_layout.addWidget(self.search_btn)

        self.parameters_cb = QCheckBox(self.search_gbox)
        self.parameters_cb.setText("")
        self.parameters_cb.setObjectName("parameters_cb")
        self.parameters_le = QLineEdit(self.search_gbox)
        self.parameters_le.setEnabled(False)
        self.parameters_le.setObjectName("parameters_le")
        search_gbox_paramaters_layout.addWidget(self.parameters_cb)
        search_gbox_paramaters_layout.addWidget(self.parameters_le)

        #### log_gbox
        self.log_gbox = QGroupBox(self.leftSplitter)
        self.log_gbox.setFlat(True)
        self.log_gbox.setObjectName("log_gbox")
        log_layout = QVBoxLayout(self.log_gbox)
        self.log_te = QTextEdit(self.log_gbox)
        self.log_te.setLineWrapMode(QTextEdit.NoWrap)
        self.log_te.setReadOnly(True)
        self.log_te.setTextInteractionFlags(Qt.TextSelectableByKeyboard | Qt.TextSelectableByMouse)
        self.log_te.setObjectName("log_te")

        self.disconnect_btn = QPushButton(self.log_gbox)
        self.disconnect_btn.setObjectName("disconnect_btn")
        self.disconnect_btn.hide()
        log_layout.addWidget(self.log_te)
        log_layout_btn = QHBoxLayout()
        log_layout.addLayout(log_layout_btn)
        log_layout_btn.addWidget(self.disconnect_btn)
        log_layout_btn.addStretch()

        #### links_gbox
        self.links_gbox = QGroupBox(self.mainSplitter)
        self.links_gbox.setFlat(True)
        self.links_gbox.setObjectName("links_gbox")
        self.links_gbox.hide()
        links_gbox_layout = QVBoxLayout(self.links_gbox)
        links_gbox_links_layout = QVBoxLayout()
        links_gbox_buttons_layout = QHBoxLayout()
        links_gbox_layout.addLayout(links_gbox_links_layout)
        links_gbox_layout.addLayout(links_gbox_buttons_layout)

        self.links_text_edit = QTextEdit(self.links_gbox)
        self.links_text_edit.setObjectName("links_text_edit")
        links_gbox_links_layout.addWidget(self.links_text_edit)

        self.export_txt_btn = QPushButton(self.links_gbox)
        self.export_txt_btn.setObjectName("export_txt_btn")
        self.export_txt_btn.setEnabled(False)
        self.export_html_btn = QPushButton(self.links_gbox)
        self.export_html_btn.setObjectName("export_html_btn")
        self.export_html_btn.setEnabled(False)

        links_gbox_buttons_layout.addWidget(self.export_txt_btn)
        links_gbox_buttons_layout.addWidget(self.export_html_btn)
        
        ### menubar
        self.menubar = QMenuBar(MainWindow)
        # self.menubar.setGeometry(QRect(0, 0, 860, 21))
        self.menubar.setObjectName("menubar")
        self.menu_file = QMenu(self.menubar)
        self.menu_file.setObjectName("menu_file")
        self.menu_help = QMenu(self.menubar)
        self.menu_help.setObjectName("menu_help")
        MainWindow.setMenuBar(self.menubar)
        self.action_about = QAction(MainWindow)
        self.action_about.setObjectName("action_about")
        self.action_About_Qt = QAction(MainWindow)
        self.action_About_Qt.setObjectName("action_About_Qt")
        self.action_exit = QAction(MainWindow)
        self.action_exit.setObjectName("action_exit")
        self.actionSave = QAction(MainWindow)
        self.actionSave.setObjectName("actionSave")
        self.action_Gmail_Advanced_Search_Syntax = QAction(MainWindow)
        self.action_Gmail_Advanced_Search_Syntax.setObjectName("action_Gmail_Advanced_Search_Syntax")
        self.menu_file.addAction(self.action_exit)
        self.menu_help.addAction(self.action_Gmail_Advanced_Search_Syntax)
        self.menu_help.addSeparator()
        self.menu_help.addAction(self.action_about)
        self.menu_help.addAction(self.action_About_Qt)
        self.menubar.addAction(self.menu_file.menuAction())
        self.menubar.addAction(self.menu_help.menuAction())
        
        self.retranslateUi(MainWindow)
        QMetaObject.connectSlotsByName(MainWindow)
        MainWindow.setTabOrder(self.client_secrets_file_path_le, self.client_secret_file_path_tBtn)
        MainWindow.setTabOrder(self.client_secret_file_path_tBtn, self.remove_account_btn)
        MainWindow.setTabOrder(self.remove_account_btn, self.add_account_btn)
        MainWindow.setTabOrder(self.add_account_btn, self.accounts_cb)
        MainWindow.setTabOrder(self.decryption_key_le, self.connect_btn)
        MainWindow.setTabOrder(self.connect_btn, self.log_te)
        MainWindow.setTabOrder(self.log_te, self.mailboxes_lw)
        MainWindow.setTabOrder(self.mailboxes_lw, self.after_date_cb)
        MainWindow.setTabOrder(self.after_date_cb, self.after_date_edit)
        MainWindow.setTabOrder(self.after_date_edit, self.before_date_cb)
        MainWindow.setTabOrder(self.before_date_cb, self.before_date_edit)
        MainWindow.setTabOrder(self.before_date_edit, self.from_le)
        MainWindow.setTabOrder(self.from_le, self.to_le)
        MainWindow.setTabOrder(self.to_le, self.subject_le)
        MainWindow.setTabOrder(self.subject_le, self.thread_count_sb)
        MainWindow.setTabOrder(self.thread_count_sb, self.html_radio)
        MainWindow.setTabOrder(self.html_radio, self.text_radio)
        MainWindow.setTabOrder(self.text_radio, self.search_btn)
        MainWindow.setTabOrder(self.search_btn, self.parameters_cb)
        MainWindow.setTabOrder(self.parameters_cb, self.parameters_le)
        MainWindow.setTabOrder(self.parameters_le, self.disconnect_btn)
        MainWindow.setTabOrder(self.disconnect_btn, self.links_text_edit)
        MainWindow.setTabOrder(self.links_text_edit, self.export_txt_btn)
        MainWindow.setTabOrder(self.export_txt_btn, self.export_html_btn)
        MainWindow.setTabOrder(self.export_html_btn, self.mailboxes_lw)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QApplication.translate("MainWindow", "Gmail URL Parser", None, QApplication.UnicodeUTF8))
        self.login_gbox.setTitle(QApplication.translate("MainWindow", "  Client secrets file path  ", None, QApplication.UnicodeUTF8))
        self.client_secrets_file_path_le.setPlaceholderText(QApplication.translate("MainWindow", "Please select your client secrets file", None, QApplication.UnicodeUTF8))
        self.lb_client_secrets_file_path.setText(QApplication.translate("MainWindow", "Path", None, QApplication.UnicodeUTF8))
        self.connect_btn.setText(QApplication.translate("MainWindow", "Connect", None, QApplication.UnicodeUTF8))
        self.client_secret_file_path_tBtn.setText(QApplication.translate("MainWindow", "...", None, QApplication.UnicodeUTF8))
        self.lb_account.setText(QApplication.translate("MainWindow", "Account", None, QApplication.UnicodeUTF8))
        self.add_account_btn.setText(QApplication.translate("MainWindow", "+", None, QApplication.UnicodeUTF8))
        self.remove_account_btn.setText(QApplication.translate("MainWindow", "-", None, QApplication.UnicodeUTF8))
        self.decryption_key_le.setPlaceholderText(QApplication.translate("MainWindow", "Decryption key", None, QApplication.UnicodeUTF8))
        self.lb_decryption_key.setText(QApplication.translate("MainWindow", "Key", None, QApplication.UnicodeUTF8))
        self.log_gbox.setTitle(QApplication.translate("MainWindow", "  Log  ", None, QApplication.UnicodeUTF8))
        self.search_gbox.setTitle(QApplication.translate("MainWindow", "  Search Parameters  ", None, QApplication.UnicodeUTF8))
        self.lb_to.setText(QApplication.translate("MainWindow", "To", None, QApplication.UnicodeUTF8))
        self.lb_from.setText(QApplication.translate("MainWindow", "From", None, QApplication.UnicodeUTF8))
        self.lb_subject.setText(QApplication.translate("MainWindow", "Subject", None, QApplication.UnicodeUTF8))
        self.search_btn.setText(QApplication.translate("MainWindow", "Search", None, QApplication.UnicodeUTF8))
        self.after_date_edit.setDisplayFormat(QApplication.translate("MainWindow", "yyyy-MM-dd", None, QApplication.UnicodeUTF8))
        self.before_date_edit.setDisplayFormat(QApplication.translate("MainWindow", "yyyy-MM-dd", None, QApplication.UnicodeUTF8))
        self.lb_select_mailbox.setToolTip(QApplication.translate("MainWindow", "<html><head/><body><p>Select multiple items to select labels</p></body></html>", None, QApplication.UnicodeUTF8))
        self.lb_select_mailbox.setText(QApplication.translate("MainWindow", "Select Mailbox or Labels", None, QApplication.UnicodeUTF8))
        self.after_date_cb.setText(QApplication.translate("MainWindow", "After", None, QApplication.UnicodeUTF8))
        self.before_date_cb.setText(QApplication.translate("MainWindow", "Before", None, QApplication.UnicodeUTF8))
        self.html_radio.setText(QApplication.translate("MainWindow", "html", None, QApplication.UnicodeUTF8))
        self.text_radio.setText(QApplication.translate("MainWindow", "text", None, QApplication.UnicodeUTF8))
        self.lb_threads.setText(QApplication.translate("MainWindow", "Threads", None, QApplication.UnicodeUTF8))
        self.links_gbox.setTitle(QApplication.translate("MainWindow", "  Links  ", None, QApplication.UnicodeUTF8))
        self.disconnect_btn.setText(QApplication.translate("MainWindow", "Disconnect", None, QApplication.UnicodeUTF8))
        self.export_txt_btn.setText(QApplication.translate("MainWindow", "Export as txt", None, QApplication.UnicodeUTF8))
        self.export_html_btn.setText(QApplication.translate("MainWindow", "Export as HTML", None, QApplication.UnicodeUTF8))
        self.menu_file.setTitle(QApplication.translate("MainWindow", "File", None, QApplication.UnicodeUTF8))
        self.menu_help.setTitle(QApplication.translate("MainWindow", "Help", None, QApplication.UnicodeUTF8))
        self.action_about.setText(QApplication.translate("MainWindow", "About", None, QApplication.UnicodeUTF8))
        self.action_About_Qt.setText(QApplication.translate("MainWindow", "About Qt", None, QApplication.UnicodeUTF8))
        self.action_exit.setText(QApplication.translate("MainWindow", "Exit", None, QApplication.UnicodeUTF8))
        self.action_exit.setShortcut(QApplication.translate("MainWindow", "Ctrl+Q", None, QApplication.UnicodeUTF8))
        self.actionSave.setText(QApplication.translate("MainWindow", "Save", None, QApplication.UnicodeUTF8))
        self.action_Gmail_Advanced_Search_Syntax.setText(QApplication.translate("MainWindow", "Gmail Advanced Search Syntax", None, QApplication.UnicodeUTF8))
Beispiel #22
0
class TwoStepLandmarkWidget(QWidget):
    """
	TwoStepLandmarkWidget
	"""

    pickedPosition = Signal()

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

        self.textFrame = QTextEdit(
            "<p>Place your mouse over the desired "
            "landmark point. Press 'Space' to shoot a ray through the volume. "
            "Move the volume around and move the mouse to move the locator. "
            "Press 'Space' again to define the final place of the landmark.</p>"
            "<p>You can also use the ray profile to define the landmark's location.</p>"
        )
        self.textFrame.setReadOnly(True)
        self.textFrame.setFrameShape(QFrame.NoFrame)
        self.textFrame.setAutoFillBackground(False)
        self.textFrame.setAttribute(Qt.WA_TranslucentBackground)
        self.textFrame.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.textFrame.setStyleSheet("background: #aaa")

        self.histogramWidget = TrackingHistogramWidget()
        self.histogramWidget.setMinimumHeight(100)
        self.histogramWidget.setVisible(False)

        self.button = QPushButton("Pick current landmark position")
        self.button.clicked.connect(self.applyButtonClicked)
        self.button.setVisible(False)

        layout = QGridLayout()
        layout.setAlignment(Qt.AlignTop)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.textFrame)
        layout.addWidget(self.histogramWidget)
        layout.addWidget(self.button)
        self.setLayout(layout)

    def setSamples(self, samples, scope=None):
        self.textFrame.setVisible(False)
        self.histogramWidget.setVisible(True)

        self.histogram = Histogram()
        self.histogram.bins = samples

        if scope:
            self.histogram.minY = scope[0]
            self.histogram.maxY = scope[1]
            self.histogram.enabled = True

        self.histogramWidget.setHistogram(self.histogram)
        self.histogramWidget.setAxeMode(left=HistogramWidget.AxeNormal)
        self.histogramWidget.nodeItem.tracking = True
        self.button.setVisible(True)

    @Slot()
    def applyButtonClicked(self):
        self.pickedPosition.emit()

    @Slot()
    def pickedLocation(self, location):
        self.histogramWidget.nodeItem.tracking = False
        self.button.setVisible(False)
Beispiel #23
0
class QLogger(logging.Handler):
    '''Code from:
  https://stackoverflow.com/questions/28655198/best-way-to-display-logs-in-pyqt
  '''
    def __init__(self,
                 parent=None,
                 format=settings.log_fmt,
                 level=logging.INFO):
        logging.Handler.__init__(self)
        # Initialize a log handler as the super class
        self.setFormatter(logging.Formatter(format))
        # Set the formatter for the logger
        self.setLevel(level)
        # Set the logging level
        self.frame = QFrame(parent)
        # Initialize a QFrame to place other widgets in

        self.frame2 = QFrame(parent)
        # Initialize frame2 for the label and checkbox
        self.label = QLabel('Logs')
        # Define a label for the frame
        self.check = QCheckBox('Debugging')
        # Checkbox to enable debugging logging
        self.check.clicked.connect(self.__changeLevel)
        # Connect checkbox clicked to the __changeLevel method

        self.log_widget = QTextEdit()
        # Initialize a QPlainTextWidget to write logs to
        self.log_widget.verticalScrollBar().minimum()
        # Set a vertical scroll bar on the log widget
        self.log_widget.horizontalScrollBar().minimum()
        # Set a horizontal scroll bar on the log widget
        self.log_widget.setLineWrapMode(self.log_widget.NoWrap)
        # Set line wrap mode to no wrapping
        self.log_widget.setFont(QFont("Courier", 12))
        # Set the font to a monospaced font
        self.log_widget.setReadOnly(True)
        # Set log widget to read only

        layout = QHBoxLayout()
        # Initialize a horizontal layout scheme for the label and checkbox frame
        layout.addWidget(self.label)
        # Add the label to the layout scheme
        layout.addWidget(self.check)
        # Add the checkbox to the layout scheme
        self.frame2.setLayout(layout)
        # Set the layout for frame to the horizontal layout

        layout = QVBoxLayout()
        # Initialize a layout scheme for the widgets
        layout.addWidget(self.frame2)
        # Add the label/checkbox frame to the layout scheme
        layout.addWidget(self.log_widget)
        # Add the text widget to the layout scheme

        self.frame.setLayout(layout)
        # Set the layout of the fram to the layout scheme defined

    ##############################################################################
    def emit(self, record):
        '''
    Overload the emit method so that it prints to the text widget
    '''
        msg = self.format(record)
        # Format the message for logging
        if record.levelno >= logging.CRITICAL:  # If the log level is critical
            self.log_widget.setTextColor(Qt.red)
            # Set text color to red
        elif record.levelno >= logging.ERROR:  # Elif level is error
            self.log_widget.setTextColor(Qt.darkMagenta)
            # Set text color to darkMagenta
        elif record.levelno >= logging.WARNING:  # Elif level is warning
            self.log_widget.setTextColor(Qt.darkCyan)
            # Set text color to darkCyan
        else:  # Else
            self.log_widget.setTextColor(Qt.black)
            # Set text color to black
        self.log_widget.append(msg)
        # Add the log to the text widget

    ##############################################################################
    def write(self, m):
        '''
    Overload the write method so that it does nothing
    '''
        pass

    ##############################################################################
    def __changeLevel(self, *args):
        '''
    Private method to change logging level
    '''
        if self.check.isChecked():
            self.setLevel(logging.DEBUG)
            # Get the Meso1819 root logger and add the handler to it
        else:
            self.setLevel(logging.INFO)
Beispiel #24
0
class MainWindow(QMainWindow):

    html_tag = re.compile("<[^>]+>")

    def _clear_log(self):
        self.log_view.clear()

    def _base_log(self, txt):
        if type(txt) == bytes:
            txt = txt.decode('utf-8', 'replace')

        if self.isVisible():
            self.log_view.append(txt)
            scrollbar = self.log_view.verticalScrollBar()
            scrollbar.setValue(scrollbar.maximum())
            app.processEvents()

        return re.sub(self.html_tag, '', txt)

    def _log(self, txt):
        self._base_log(txt)

    def _log_error(self, txt):
        m = "<b><font color='red'>{}</font></b>".format(txt)
        self._base_log(m)

    def _log_warning(self, txt):
        m = "<b><font color='orange'>{}</font></b>".format(txt)
        self._base_log(m)

    def _log_success(self, txt):
        self._log("<b><font color='green'>{}</font></b>".format(txt))

    def _run_detached_shell(self, cmd):
        DETACHED_PROCESS = 0x00000008
        CREATE_NEW_PROCESS_GROUP = 0x00000200
        self._log("Executing : " + " ".join(cmd))
        popen = subprocess.Popen(cmd,
                                 stdin=subprocess.PIPE,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 creationflags=DETACHED_PROCESS
                                 | CREATE_NEW_PROCESS_GROUP)

    def _run_shell(self, cmd, env=dict()):

        self._log("About to run {}".format(" ".join(cmd)))

        if env and platform.system() == "Windows":

            # For some reason, on widnows, using enviro variables
            # disturbs popen when trying to connect to the DB via psql.
            # I suspect that's more a problem with postgresql authentification
            # scheme, but after playing a bit with PG's config files
            # I wasn't able to turn something up...

            self._log("We're on Windows, I can't use environment variables...")
            env = None

        try:
            popen = subprocess.Popen(cmd,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE,
                                     env=env,
                                     universal_newlines=True)
        except Exception as ex:
            self._log_error("Can't run the command because {}".format(ex))
            raise ex

        # I used "poll" to follow the command's execution
        # but there were many issues (Python's doc talks about
        # deadlocks, I think that's what I've seen)

        stdout_data, stderr_data = popen.communicate()

        self._log(stdout_data)
        self._log(stderr_data)

        self._log("Returned {} ".format(int(popen.returncode)))
        return int(popen.returncode), stdout_data, stderr_data

    def _exec_out_of_transaction(self, sql):
        # Some Postgres administrative commands cannot run inside
        # a transaction. Unfortunately, SQLA tries very hard
        # to put us in a transaction at any time.
        # This is a small hack to leave the transaction.

        connection = db_engine().connect()
        connection.execute("commit")  # Get out of SQLA's transaction
        self._log(sql)
        connection.execute(sql)
        connection.close()

    def _confirm_dangerous_operation(self):
        d = YesConfirm(self)
        d.exec_()
        return d.result() == QDialog.Accepted

    def _unzip_version(self, zipName, tmp_dir=""):

        shutil.rmtree(tmp_dir)

        z = zipfile.ZipFile(zipName)
        for f in z.namelist():
            dest = os.path.join(tmp_dir, f.replace('/', os.sep))
            if f.endswith('/'):
                os.makedirs(dest)
            else:
                z.extract(f, tmp_dir)
        z.close()

    def _update_config(self, pg_url, host, port, path_cfg, path_spec):
        cfg = configobj.ConfigObj(infile=path_cfg, configspec=path_spec)
        cfg['Database']['url'] = pg_url
        cfg['DownloadSite']['url_file'] = 'http://{}:{}/file'.format(
            host, port)
        cfg['DownloadSite']['url_version'] = 'http://{}:{}/version'.format(
            host, port)
        cfg.write()

    def _zip_version(self, source_path, dest_path):
        z = zipfile.ZipFile(dest_path, "w", zipfile.ZIP_DEFLATED)

        for root, dirs, files in os.walk(source_path):
            for filename in files:
                # print source_path, root, filename

                fn = os.path.join(root, filename)
                arcname = os.path.join(root, filename).replace(source_path, "")
                z.write(fn, arcname=arcname)

        z.close()

    def _upgrade_client_to_version(self, version, pg_url, host, port):

        tmp_dir = "c:\\tmp"
        unzip_dir = os.path.join(tmp_dir, "azer")

        # Grab the zip
        # original_file = self._download_version(version,tmp_dir)
        original_file = os.path.join(tmp_dir, "horse-{}.zip".format(version))

        self._unzip_version(original_file, unzip_dir)

        self._update_config(
            pg_url, host, port,
            os.path.join(unzip_dir, "koi", "resources", "config.cfg"),
            os.path.join(unzip_dir, "koi", "resources", "config-check.cfg"))

        self._zip_version(unzip_dir, original_file)

    def _extract_db_params_from_url(self, url):
        parsed_url = urlparse(url)
        dbname = parsed_url.path[1:]
        login_pw_re = re.compile("^([^:]+):([^@]+)@([^:]+):?([0-9]+)?")
        login, password, host, port = login_pw_re.match(
            parsed_url.netloc).groups()
        return login, password, dbname, host, port

    def upgrade_client(self):

        d = VersionDialog(self)
        d.exec_()
        if d.result() == QDialog.Accepted:

            pg_url = self.public_url_edit.text()
            host = re.search("(@.*:)",
                             pg_url).groups()[0].replace("@",
                                                         "").replace(":", "")
            port = configuration.get("DownloadSite", "port")

            self._upgrade_client_to_version("1.0.42", pg_url, host, port)

    @Slot(bool)
    def restore_backup(self):

        self._clear_log()
        self._log("Restore procedure started")

        url = self.url_edit.text()
        psql_path = configuration.get("Commands", "psql")

        if not psql_path:
            self._log_error(
                "The Commands/psql path is not set in the server.cfg")
            self._log("Please fix the configuration file (on the right)")
            return

        if not configuration.get("Commands", "pg_restore"):
            self._log_error(
                "The Commands/pg_restore path is not set in the server.cfg")
            self._log("Please fix the configuration file (on the right)")
            return

        if not configuration.get("Backup", "backup_directory"):

            self._log(
                "The Backup/backup_directory path is not set in the server.cfg"
            )
            self._log("I'm setting it myself.")

            configuration.set("Backup", "backup_directory", get_data_dir())
            configuration.set("DocumentsDatabase", "documents_root",
                              os.path.join(get_data_dir(), "documents"))
            configuration.save()
            self.edit_config.load_configuration()

        login_clt, password_clt, dummy, dummy, dummy = self._extract_db_params_from_url(
            configuration.get("Database", "url"))
        login_adm, password_adm, dbname, host, port = self._extract_db_params_from_url(
            configuration.get("Database", "admin_url"))

        self._log("{} / {}".format(login_adm, password_adm))

        full_path_backup = None
        d = ""
        if configuration.get("Backup", "backup_directory"):
            d = configuration.get("Backup", "backup_directory")

        if platform.system() == "Windows":

            if configuration.get("Backup", "backup_directory"):
                d = configuration.get("Backup", "backup_directory")

            # Using the static method gives a more native FileDialog.
            # with support for network
            backup_file = QFileDialog.getOpenFileName(
                self, _("Please select a backup file"), d,
                "{} database backup (*.pgbackup)".format(
                    configuration.get("Globals", "name")))[0]

            if not backup_file:
                self._log("Restore aborted")
                return

            full_path_backup = backup_file
            if not os.path.isdir(full_path_backup):
                self._log(
                    "{} is not a directory, so I'll go up a level".format(
                        full_path_backup))
                full_path_backup = os.path.dirname(full_path_backup)

                if not os.path.isdir(full_path_backup):
                    self._log_error(
                        "{} is not a directory either. Aborting restore.".
                        format(full_path_backup))
                    return

        elif platform.system() == "Linux":

            d = AskWindowsShare(None)
            d.exec_()
            if d.result() == QDialog.Accepted:

                # //192.168.0.6/postgresqlbackup

                script_path = "/tmp/horse_mount.sh"
                script = open(script_path, "w")
                script.write("""#!/bin/bash
echo "Creating transfer directory"
mkdir /tmp/backup_win
echo "Unmounting previous transfer directory (can fail)"
umount /tmp/backup_win
echo "Mouting the backup directory"
mount -t cifs -ousername={},password={} {} /tmp/backup_win
                """.format(d.user.text().strip(),
                           d.password.text().strip(),
                           d.address.text().strip()))
                script.close()

                import stat
                os.chmod(script_path,
                         stat.S_IEXEC | stat.S_IWRITE | stat.S_IREAD)

                cmd = [
                    'gksudo', '--sudo-mode', '--message',
                    'Allow Koi to connect to the backup server.', script_path
                ]

                # gksudo seems to like to have the DISPLAY set. So I basically copy
                # it from the calling environment.

                ret, dummy, dummy = self._run_shell(
                    cmd, {'DISPLAY': os.environ.get('DISPLAY')})

                if ret > 0:
                    self._log_error(
                        "The mount operation failed. Please review the parameters you've given."
                    )
                    self._log_error(
                        "Network address : {}, windows user name : {}".format(
                            d.address.text() or "?",
                            d.user.text() or "?"))
                    return

                full_path_backup = "/tmp/backup_win"
            else:
                dialog = QFileDialog(self)
                dialog.setFileMode(QFileDialog.Directory)
                dialog.setNameFilters(['Koi database backup (*.pgbackup)'])
                dialog.setWindowTitle("Please select a backup file")
                if configuration.get("Backup", "backup_directory"):
                    dialog.setDirectory(
                        configuration.get("Backup", "backup_directory"))
                if dialog.exec_():
                    full_path_backup = dialog.selectedFiles()[0]
                else:
                    self._log_error(
                        "Without proper source directory, I can't continue !")
                    return
        else:
            self._log_error("Unsupported operating system")

        # At this poitn full_path_backup is the path to the backup
        # directory of Horse that we want to restore.
        # It is different than the current backup directory.

        if full_path_backup:
            full_restore(configuration, full_path_backup, backup_file, True,
                         mainlog)
            self._log_success("Backup successfully restored !")

    def create_root_account(self):
        if not configuration.get("Database", "url"):
            self._log_error("Can't read Database/url ini config file")
            return

        login = "******"
        password = "******"

        self._clear_log()
        self._log("<b>Creating or recreating a root account")
        try:
            init_db_session(configuration.get("Database", "url"))
            create_root_account(login, password)
            self._log_success(
                "Root account successfully reset to login:{}, password:{}".
                format(login, password))
        except Exception as ex:
            self._log_error("Root account creation failed")
            self._log_error(ex)

    def create_database(self, localhost=False):

        # If in command line, skip requesting confirmation for database creation
        if self.isVisible() and not self._confirm_dangerous_operation():
            return

        self._clear_log()

        if not configuration.get("Database", "admin_url"):
            self._log_error("Can't read Database/admin_url ini config file")
            return

        if not configuration.get("Database", "url"):
            self._log_error("Can't read Database/url ini config file")
            return

        admin_url = configuration.get("Database", "admin_url")
        local_url = configuration.get("Database", "url")

        if check_postgres_connection(configuration.get("Database",
                                                       "admin_url")):
            self._log("Successfuly connected to PostgreSQL server")
        else:
            self._log_error("Failed to connect to PostgreSQL server")
            return False

        self._log("<b>Creating a database")
        try:
            create_blank_database(configuration.get("Database", "admin_url"),
                                  configuration.get("Database", "url"))
            self._log("<b><font color='green'>Database created")
        except Exception as ex:
            self._log_error("Database creation failed")
            self._log_error(ex)

        disconnect_db()
        return

    def check_database(self):
        self._clear_log()

        url = self.url_edit.text()

        self._log("<b>Checking database at {}".format(url))

        service_installed = False

        if platform.system() == "Windows":
            cmd = ["sc", "query", self.POSTGRESQL_SERVICE_NAME]
            service_installed, stdout, stderr = self._run_shell(cmd)

            if check_postgres_connection(url):

                self._log_success(
                    "Successfuly connected with the PostgreSQLserver")
                if service_installed == 0:
                    self._log(
                        "The {} Windows service seems installed correctly. So the database should resist to a reboot."
                        .format(self.POSTGRESQL_SERVICE_NAME))
                else:
                    self._log_error(
                        "I didn't find the {} service in Windows services. Did the installation complete correctly ? If this PC restarts, the database won't start, making the system unusable."
                        .format(self.POSTGRESQL_SERVICE_NAME))

            else:
                self._log_error("Unable to connect to PostgreSQL server.")
                if service_installed == 0:
                    self._log(
                        "The {} service seems installed though. You should locate it in Windows services and start it"
                        .format(self.POSTGRESQL_SERVICE_NAME))
                else:
                    self._log(
                        "The {} service is not installed. You should try to install with (see Install services button in this program) or, if that doesn't work, install it manually."
                        .format(self.POSTGRESQL_SERVICE_NAME))

                return False

        disconnect_db()
        init_db_session(url, None, False)

        # check = check_database_connection()
        # if  check == True:
        #     self._log_success("Successfuly connected to database")
        # else:
        #     self._log(u"Failed to connect to database. Maybe you should create it or restore a backup ? Error was :")
        #     self._log_error(check)
        #     return False
        #
        # self._log("")

        r = check_active_postgres_connections()
        disconnect_db()

        if r > 1:
            self._log("There are {} other people connected".format(r))
            self._log("The database seems fine".format(r))
            return False
        elif r == 1:
            self._log("Nobody connected to the database (besides us)")
            self._log("The database seems fine".format(r))
        else:
            self._log_error("Can't check number of connected people...")
            # self._log("The database seems broken".format(r))
            return False

        return True

    def check_server(self):
        self._clear_log()
        self._log("<b>Checking web server")

        # Because of difficulties with cxFreeze and cherrypy and windows service, the
        # Koi windows service is not installed; only a scheduled taks is installed.

        # if platform.system() == "Windows":
        #
        #     cmd = ["sc", "query", self.SERVER_NAME+self.SERVER_NAME_SUFFIX]
        #
        #     try:
        #         if self._run_shell(cmd):
        #             self._log_error("Can't find the server's Windows service ({}). Check your installation or use 'Install services'. If this PC restarts, the server won't start, making the system unusable.".format(self.SERVER_NAME+self.SERVER_NAME_SUFFIX))
        #             return
        #     except Exception as ex:
        #         return

        v = get_server_version(configuration.update_url_version)

        db_url = None
        try:
            self._log("Looking for advertised DB version at {}".format(
                configuration.database_url_source()))
            response = urlopen(configuration.database_url_source(), timeout=2)
            db_url = response.read()
        except Exception as ex:
            self._log_error(
                "Unable to connect to the web server. Is it running ? I tried to get the databse url from it. If the server is running, check the configuration at DownloadSite/base_url and verify it's good."
            )

            HOST = guess_server_public_ip()
            self._log(
                "Looking again for advertised DB version at {}".format(HOST))
            response = urlopen("http://{}".format(HOST), timeout=2)
            db_url = response.read()

            pass

        if v and db_url:
            self._log("Server version : {}".format(v))
            self._log("Public announced database : {}".format(db_url))
            self._log("")
            self._log("<b><font color='green'>Server is fine")
        else:
            self._log_error(
                "Server didn't answer. Maybe you should start it manually ?")

    def stop_server_manually(self):
        self._clear_log()
        self._log("<b>Shutting down server...")

        cmd = ["taskkill", "/F", "/IM", "horse_server_console.exe"]
        self._run_shell(cmd)

        cmd = [
            configuration.get("Commands", "pg_ctl"), "-D",
            configuration.get("Database", "db_path"), "stop"
        ]
        self._run_shell(cmd)
        self._log("<b>Server shut down")

    def start_server_manually(self):
        self._clear_log()
        self._log("<b>Starting server...")

        cmd = [configuration.get("Commands", "horse_server_console")]
        self._run_detached_shell(cmd)

        cmd = [
            configuration.get("Commands", "pg_ctl"), "-D",
            configuration.get("Database", "db_path"), "start"
        ]
        self._run_detached_shell(cmd)

        self._log("<b>Server started")

    POSTGRESQL_SERVICE_NAME = "Postgresql"  # No space here !
    SERVER_NAME = "HorseService"  # No space here !
    SERVER_NAME_SUFFIX = "Production"
    BACKUP_NAME = "HorseBackup"

    def install_on_start_tasks(self):
        self.stop_server_manually()

        self._clear_log()
        self._log("<b>Installing on-start services...")
        self._log(
            "Installing backup as a scheduled task (once every night)...")
        cmd = [
            "SCHTASKS", "/Create", "/F", "/SC", "DAILY", "/ST", "00:30", "/TN",
            self.BACKUP_NAME, "/TR",
            configuration.get("Commands", "horse_backup")
        ]
        self._run_shell(cmd)

        # self._log("Installing webserver as a scheduled task (once at startup)...")
        # cmd = ["SCHTASKS","/Create","/F","/SC","ONSTART","/TN",self.XXX,"/TR",configuration.get("Commands","horse_server")]
        # self._run_shell(cmd)

    def install_service(self):
        self.stop_server_manually()

        self._clear_log()
        self._log("<b>Installing services...")
        self._log("Installing backup as a scheduled task...")
        cmd = [
            "SCHTASKS", "/Create", "/F", "/SC", "DAILY", "/ST", "00:30", "/TN",
            "HorseDailyBackup", "/TR",
            configuration.get("Commands", "horse_backup")
        ]
        self._run_shell(cmd)

        self._log("Installing PostgreSQL as a service...")

        cmd = [
            configuration.get("Commands", "pg_ctl"), "register", "-N",
            self.POSTGRESQL_SERVICE_NAME, "-D",
            configuration.get("Database", "db_path")
        ]
        self._run_shell(cmd)
        cmd = ["sc", "start", self.POSTGRESQL_SERVICE_NAME]
        self._run_shell(cmd)
        cmd = ["sc", "query", self.POSTGRESQL_SERVICE_NAME]
        self._run_shell(cmd)

        self._log("Installing server as a service...")
        cmd = [
            configuration.get("Commands", "horse_server"), "--install",
            self.SERVER_NAME_SUFFIX
        ]
        self._run_shell(cmd)

        self._log("<b>Services installed")

        cmd = ["sc", "start", self.SERVER_NAME + self.SERVER_NAME_SUFFIX]
        self._run_shell(cmd)

    def uninstall_service(self):
        self._clear_log()
        self._log("<b>Uninstalling services...")
        self._log("Uninstalling backup as a scheduled task...")
        cmd = ["SCHTASKS", "/Delete", "/F", "/TN",
               "HorseDailyBackup"]  # /F to avoid an interactive confirmation
        self._run_shell(cmd)

        self._log("Uninstalling PostgreSQL as a service...")

        cmd = ["sc", "stop", self.POSTGRESQL_SERVICE_NAME]
        self._run_shell(cmd)

        cmd = [
            configuration.get("Commands", "pg_ctl"), "unregister", "-N",
            self.POSTGRESQL_SERVICE_NAME, "-D",
            configuration.get("Database", "db_path")
        ]
        self._run_shell(cmd)

        self._log("Uninstalling server as a service...")
        cmd = [configuration.get("Commands", "horse_server"), "remove"]
        self._run_shell(cmd)

        self._log("<b>Services uninstalled")

    def show_intro(self):
        self._log("<b>This is {} !".format(configuration.get(
            "Globals", "name")))

        self._log("<b>" + copyright())
        self._log("<b>" + license_short())
        self._log("")

        if platform.system() == "Windows" and not isUserAdmin():
            self._log_warning(
                "You don't have amdinistrative rights ! Therefore some of the functionality in this program won't work."
            )
            self._log(
                "To change that, use the 'run as administrator' functionality of Windows. Right-click on the {} admnististration program in the start menu and select 'run as administrator'"
                .format(configuration.get("Globals", "name")))

        if self.check_backup_directory() != True:
            self._log_error("The backup directory is not correct !")

    def check_backup_directory(self):
        self._log("Testing the backup directory")
        directory = configuration.get("Backup", "backup_directory")
        try:
            f = open(os.path.join(directory, "test_file"), "w")
            f.write("TestBackup")
            f.close()
            self._log("<b><font color='green'>Backup directory is fine !")
            return True
        except Exception as ex:
            return str(ex)

    def set_backup_directory(self):
        dialog = QFileDialog(self)
        dialog.setFileMode(QFileDialog.Directory)
        dialog.setOption(QFileDialog.ShowDirsOnly, True)
        dialog.setWindowTitle("Please select a backup directory")

        if configuration.get("Backup", "backup_directory"):
            dialog.setDirectory(configuration.get("Backup",
                                                  "backup_directory"))

        if dialog.exec_():
            mainlog.debug(dialog.selectedFiles())
            directory = dialog.selectedFiles()[0]

            self._log("Testing the backup directory")
            try:
                f = open(os.path.join(directory, "test_file"), "w")
                f.write("TestBackup")
                f.close()
            except Exception as ex:
                box = QMessageBox(
                    QMessageBox.Warning,
                    "Unable to write into the backup directory",
                    u"I can't write in the backup directory you selected. Have I the necessary permissions  on that directory ({})? The error was : {}"
                    .format(directory, str(ex)))
                box.exec_()
                return

            self.backup_directory_edit.setText(directory)

            configuration.set("Backup", "backup_directory", directory)

            self._log("Saving the backup directory in the configuration")
            configuration.save()

        dialog.close()

    def show_client_dowload_page(self):
        import webbrowser

        self._log("<hr>")

        url = configuration.get("DownloadSite", "public_url")
        self._log(
            "<b>Opening delivery_slips download page at : {}".format(url))

        if True or url:
            try:
                webbrowser.open(url)
            except Exception as ex:
                self._log_error(
                    "Unable to open the page because of an error: {}".format(
                        ex))
        else:
            self._log(
                "Could not open the delivery_slips page because URL is empty. The configuration is not good."
            )

    def set_public_ip(self):
        d = AskIPAddress(self)
        d.exec_()
        guessed_ip = d.address.text()

        ip_in_zip = load_public_ip()
        if ip_in_zip != guessed_ip:
            if confirmationBox(
                    _("Setting IP addresse in delivery_slips zip"),
                    _("The IP address configured in the zipped delivery_slips ({}) is not the "
                      +
                      "same as the one you gave ({}). Maybe the server has " +
                      "changed network. Should I fix that ?").format(
                          ip_in_zip, guessed_ip)):
                inject_public_ip_in_client(guessed_ip)

        server_ip = configuration.get("DEFAULT", "public_ip")
        if guessed_ip != server_ip:
            if confirmationBox(
                    _("Setting IP addresse in server configuration"),
                    _("The IP address configured for the server ({}) is not the "
                      +
                      "same as the one you gave ({}). Maybe the server has " +
                      "changed network. Should I fix that ?").format(
                          server_ip, guessed_ip)):

                configuration.set("DEFAULT", "public_ip", guessed_ip)
                configuration.save()
                window.edit_config.load_configuration()

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

        self.edit_config = EditConfigurationDialog(self)
        self.edit_config.load_configuration()

        w = QWidget(self)

        big_hlayout = QHBoxLayout()

        layout = QVBoxLayout()
        big_hlayout.addLayout(layout)
        big_hlayout.addWidget(self.edit_config)

        layout.addWidget(
            QLabel("<h1>{} administration</h1>".format(
                configuration.get("Globals", "name"))))

        glayout = QGridLayout()

        row = 0

        HOST = "{} or {}".format(guess_server_public_ip(),
                                 socket.gethostname())
        glayout.addWidget(QLabel("<b>Server's IP address"), row, 0)
        ip_address = configuration.get("DEFAULT", "public_ip")
        if not ip_address:
            ip_address = "<font color='red'><b>NOT DEFINED</b></font>"
        glayout.addWidget(QLabel("{} (guessed: {})".format(ip_address, HOST)),
                          row, 1)

        row += 1
        glayout.addWidget(QLabel("<b>Client database URL"), row, 0)
        db_url = configuration.get("Database", "url")
        self.public_url_edit = QLabel(db_url)
        glayout.addWidget(self.public_url_edit, row, 1)

        row += 1
        glayout.addWidget(QLabel("<b>Client server URL"), row, 0)
        url = configuration.get("DownloadSite", "public_url")
        self.public_web_url_edit = QLabel(url)
        glayout.addWidget(self.public_web_url_edit, row, 1)

        row += 1
        glayout.addWidget(QLabel("Server local DB URL"), row, 0)
        db_url = configuration.get("Database", "admin_url")
        self.url_edit = QLabel(db_url)
        glayout.addWidget(self.url_edit, row, 1)

        row += 1
        glayout.addWidget(QLabel("Backup directory"), row, 0)
        db_url = configuration.get("Backup", "backup_directory")
        self.backup_directory_edit = QLabel(db_url)
        glayout.addWidget(self.backup_directory_edit, row, 1)

        row += 1
        glayout.addWidget(QLabel("Data/logs directory"), row, 0)
        self.data_directory_edit = QLabel(get_data_dir())
        glayout.addWidget(self.data_directory_edit, row, 1)

        qgb = QGroupBox("Life data")
        qgb.setLayout(glayout)
        layout.addWidget(qgb)

        hlayout = QHBoxLayout()
        b = QPushButton("Check database")
        b.clicked.connect(self.check_database)
        hlayout.addWidget(b)

        b = QPushButton("Check web server")
        b.clicked.connect(self.check_server)
        hlayout.addWidget(b)

        b = QPushButton("Show delivery_slips download page")
        b.clicked.connect(self.show_client_dowload_page)
        hlayout.addWidget(b)

        qgb = QGroupBox("Checks")
        qgb.setLayout(hlayout)
        layout.addWidget(qgb)

        hlayout = QHBoxLayout()
        # b = QPushButton("Set backup directory")
        # b.clicked.connect(self.set_backup_directory)
        # hlayout.addWidget( b)

        b = QPushButton("Restore backup")
        b.clicked.connect(self.restore_backup)
        hlayout.addWidget(b)

        b = QPushButton("Reset admin account")
        b.clicked.connect(self.create_root_account)
        hlayout.addWidget(b)

        # b = QPushButton("Set public IP")
        # b.clicked.connect(self.set_public_ip)
        # hlayout.addWidget( b)

        # Please use the command line, this is not for the faint hearted.

        # b = QPushButton("Clear database")
        # b.clicked.connect(self.create_database)
        # hlayout.addWidget( b)

        qgb = QGroupBox("Actions")
        qgb.setLayout(hlayout)
        layout.addWidget(qgb)

        vlayout = QVBoxLayout()

        # if platform.system() == 'Windows':
        #     # when running on Linux, it's expected that the
        #     # whole server configuration is set up by us
        #
        #     hlayout = QHBoxLayout()
        #     b = QPushButton("Start server manually")
        #     b.clicked.connect(self.start_server_manually)
        #     hlayout.addWidget( b)
        #
        #     b = QPushButton("Stop server manually")
        #     b.clicked.connect(self.stop_server_manually)
        #     hlayout.addWidget( b)
        #     vlayout.addLayout(hlayout)
        #
        #     hlayout = QHBoxLayout()
        #     b = QPushButton("Install services")
        #     b.clicked.connect(self.install_service)
        #     hlayout.addWidget( b)
        #
        #     b = QPushButton("Uninstall services")
        #     b.clicked.connect(self.uninstall_service)
        #     hlayout.addWidget( b)
        #     vlayout.addLayout(hlayout)
        #
        #     b = QPushButton("Install scheduled services")
        #     b.clicked.connect(self.install_on_start_tasks)
        #     vlayout.addWidget( b)
        #
        #     # b = QPushButton("Upgrade delivery_slips")
        #     # b.clicked.connect(self.upgrade_client)
        #     # layout.addWidget( b)
        #
        #     qgb = QGroupBox("Service & installation")
        #     qgb.setLayout(vlayout)
        #     layout.addWidget(qgb)

        self.log_view = QTextEdit()
        layout.addWidget(self.log_view)

        self.url_edit.setTextInteractionFlags(Qt.TextSelectableByMouse)
        self.public_url_edit.setTextInteractionFlags(Qt.TextSelectableByMouse)
        self.public_web_url_edit.setTextInteractionFlags(
            Qt.TextSelectableByMouse)
        self.backup_directory_edit.setTextInteractionFlags(
            Qt.TextSelectableByMouse)

        self.log_view.setReadOnly(True)

        w.setLayout(big_hlayout)

        self.setCentralWidget(w)
Beispiel #25
0
class TransferPanel(QWidget):
    '''
    Transfer Panel
    
    This Panel is the main dialog box for the Dive Computer Transfer GUI
    '''
    def __init__(self, parent=None):
        super(TransferPanel, self).__init__(parent)
        
        self._logbook = None
        self._logbookName = 'None'
        self._logbookPath = None
        
        self._createLayout()
        
        self._readSettings()
        self.setWindowTitle(self.tr('DC Transfer - %s') % self._logbookName)
        
    def _createLayout(self):
        'Create the Widget Layout'
        
        self._txtLogbook = QLineEdit()
        self._txtLogbook.setReadOnly(True)
        self._lblLogbook = QLabel(self.tr('&Logbook File:'))
        self._lblLogbook.setBuddy(self._txtLogbook)
        self._btnBrowse = QPushButton('...')
        self._btnBrowse.clicked.connect(self._btnBrowseClicked)
        self._btnBrowse.setStyleSheet('QPushButton { min-width: 24px; max-width: 24px; }')
        self._btnBrowse.setToolTip(self.tr('Browse for a Logbook'))
        
        self._cbxComputer = QComboBox()
        self._lblComputer = QLabel(self.tr('Dive &Computer:'))
        self._lblComputer.setBuddy(self._cbxComputer)
        self._btnAddComputer = QPushButton(QPixmap(':/icons/list-add.png'), self.tr(''))
        self._btnAddComputer.setStyleSheet('QPushButton { min-width: 24px; min-height: 24; max-width: 24px; max-height: 24; }')
        self._btnAddComputer.clicked.connect(self._btnAddComputerClicked)
        self._btnRemoveComputer = QPushButton(QPixmap(':/icons/list-remove.png'), self.tr(''))
        self._btnRemoveComputer.setStyleSheet('QPushButton { min-width: 24px; min-height: 24; max-width: 24px; max-height: 24; }')
        self._btnRemoveComputer.clicked.connect(self._btnRemoveComputerClicked)
        
        hbox = QHBoxLayout()
        hbox.addWidget(self._btnAddComputer)
        hbox.addWidget(self._btnRemoveComputer)
        
        gbox = QGridLayout()
        gbox.addWidget(self._lblLogbook, 0, 0)
        gbox.addWidget(self._txtLogbook, 0, 1)
        gbox.addWidget(self._btnBrowse, 0, 2)
        gbox.addWidget(self._lblComputer, 1, 0)
        gbox.addWidget(self._cbxComputer, 1, 1)
        gbox.addLayout(hbox, 1, 2)
        gbox.setColumnStretch(1, 1)
        
        self._pbTransfer = QProgressBar()
        self._pbTransfer.reset()
        self._txtStatus = QTextEdit()
        self._txtStatus.setReadOnly(True)
        
        self._btnTransfer = QPushButton(self.tr('&Transfer Dives'))
        self._btnTransfer.clicked.connect(self._btnTransferClicked)
        
        self._btnExit = QPushButton(self.tr('E&xit'))
        self._btnExit.clicked.connect(self.close)
        
        hbox = QHBoxLayout()
        hbox.addWidget(self._btnTransfer)
        hbox.addStretch()
        hbox.addWidget(self._btnExit)
        
        vbox = QVBoxLayout()
        vbox.addLayout(gbox)
        vbox.addWidget(self._pbTransfer)
        vbox.addWidget(self._txtStatus)
        vbox.addLayout(hbox)
        
        self.setLayout(vbox)
        
    def _closeLogbook(self):
        'Close the current Logbook'
        if self._logbook is None:
            return
        
        self._logbook = None
        self._logbookName = 'None'
        self._logbookPath = None
        
        self._txtLogbook.clear()
        self._cbxComputer.setModel(None)
        
        self._writeSettings()
        self.setWindowTitle(self.tr('DC Transfer - %s') % self._logbookName)
        
    def _openLogbook(self, path):
        'Open an existing Logbook'
        if self._logbook is not None:
            self._closeLogbook()
            
        if not os.path.exists(path):
            QMessageBox.critical(self, self.tr('Missing Logbook'), 
                self.tr('Logbook File "%s" does not exist.') % path)
            return
        
        #TODO: Handle a Schema Upgrade in a user-friendly manner
        self._logbook = Logbook(path, auto_update=False)
        self._logbookName = os.path.basename(path)
        self._logbookPath = path
        
        self._txtLogbook.setText(self._logbookPath)
        self._cbxComputer.setModel(DiveComputersModel(self._logbook))
        
        self._writeSettings()
        self.setWindowTitle(self.tr('DC Transfer - %s') % self._logbookName)
        
    def _readSettings(self):
        'Read main window settings from the configuration'
        settings = QSettings()
        settings.beginGroup('MainWindow')
        max = settings.value('max')
        size = settings.value('size')
        pos = settings.value('pos')
        file = settings.value('file')
        settings.endGroup()
        
        # Size and Position the Main Window
        if size is not None:
            self.resize(size)
        if pos is not None:
            self.move(pos)
            
        # HAX because QVariant is not exposed in PySide and the default
        # coercion to string is just stupid
        if max is not None and (max == 'true'):
            self.showMaximized()
        
        # Open the Logbook
        if file is not None:
            self._openLogbook(file)
        
    def _writeSettings(self):
        'Write settings to the configuration'
        settings = QSettings()
        settings.beginGroup('MainWindow')
        settings.setValue('pos', self.pos())
        settings.setValue('size', self.size())
        settings.setValue('max', self.isMaximized())
        settings.setValue('file', self._logbookPath)
        settings.endGroup()
        
    def closeEvent(self, e):
        'Intercept an OnClose event'
        self._writeSettings()
        e.accept()
        
    #--------------------------------------------------------------------------
    # Slots
    
    @QtCore.Slot()
    def _btnAddComputerClicked(self):
        'Add a Dive Computer'
        dc = AddDiveComputerWizard.RunWizard(self)
        
        if dc is not None:
            self._logbook.session.add(dc)
            self._logbook.session.commit()
            self._cbxComputer.model().reload()
            self._cbxComputer.setCurrentIndex(self._cbxComputer.findText(dc.name))
    
    @QtCore.Slot()
    def _btnRemoveComputerClicked(self):
        'Remove a Dive Computer'
        idx = self._cbxComputer.currentIndex()
        dc = self._cbxComputer.itemData(idx, Qt.UserRole+0)
        if QMessageBox.question(self, self.tr('Delete Dive Computer?'), 
                    self.tr('Are you sure you want to delete "%s"?') % dc.name,
                    QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) == QMessageBox.Yes:
            self._logbook.session.delete(dc)
            self._logbook.session.commit()
            self._cbxComputer.model().reload()
    
    @QtCore.Slot()
    def _btnBrowseClicked(self):
        'Browse for a Logbook File'
        if self._logbook is not None:
            dir = os.path.dirname(self._logbookPath)
        else:
            dir = os.path.expanduser('~')
        
        fn = QFileDialog.getOpenFileName(self,
            caption=self.tr('Select a Logbook file'), dir=dir,
            filter='Logbook Files (*.lbk);;All Files(*.*)')[0]    
        if fn == '':
            return
        if not os.path.exists(fn):
            if QMessageBox.question(self, self.tr('Create new Logbook?'), 
                    self.tr('Logbook "%s" does not exist. Would you like to create it?') % os.path.basename(fn),
                    QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) != QMessageBox.Yes:
                return
            Logbook.Create(fn)
        self._openLogbook(fn)
        
    @QtCore.Slot()
    def _btnTransferClicked(self):
        'Transfer Dives'
        idx = self._cbxComputer.currentIndex()
        dc = self._cbxComputer.itemData(idx, Qt.UserRole+0)
        
        if self._logbook.session.dirty:
            print "Flushing dirty session"
            self._logbook.rollback()
        
        self._txtLogbook.setEnabled(False)
        self._btnBrowse.setEnabled(False)
        self._cbxComputer.setEnabled(False)
        self._btnAddComputer.setEnabled(False)
        self._btnRemoveComputer.setEnabled(False)
        self._btnTransfer.setEnabled(False)
        self._btnExit.setEnabled(False)
        
        self._txtStatus.clear()
        
        thread = QThread(self)
        
        #FIXME: ZOMG HAX: Garbage Collector will eat TransferWorker when moveToThread is called
        #NOTE: Qt.QueuedConnection is important...
        self.worker = None
        self.worker = TransferWorker(dc)
        thread.started.connect(self.worker.start, Qt.QueuedConnection)
        self.worker.moveToThread(thread)
        self.worker.finished.connect(self._transferFinished, Qt.QueuedConnection)
        self.worker.finished.connect(self.worker.deleteLater, Qt.QueuedConnection)
        self.worker.finished.connect(thread.deleteLater, Qt.QueuedConnection)
        self.worker.progress.connect(self._transferProgress, Qt.QueuedConnection)
        self.worker.started.connect(self._transferStart, Qt.QueuedConnection)
        self.worker.status.connect(self._transferStatus, Qt.QueuedConnection)
        
        thread.start()
        
    @QtCore.Slot(str)
    def _transferStatus(self, msg):
        'Transfer Status Message'
        self._txtStatus.append(msg)
        
    @QtCore.Slot(int)
    def _transferStart(self, nBytes):
        'Transfer Thread Stated'
        if nBytes > 0:
            self._pbTransfer.setMaximum(nBytes)
        else:
            self._pbTransfer.setMaximum(100)
        self._pbTransfer.reset()
        
    @QtCore.Slot(int)
    def _transferProgress(self, nTransferred):
        'Transfer Thread Progress Event'
        self._pbTransfer.setValue(nTransferred)
        
    @QtCore.Slot(models.Dive)
    def _transferParsed(self, dive):
        'Transfer Thread Parsed Dive'
        self._logbook.session.add(dive)
        
    @QtCore.Slot()
    def _transferFinished(self):
        'Transfer Thread Finished'
        self._logbook.session.commit()
        
        self._txtLogbook.setEnabled(True)
        self._btnBrowse.setEnabled(True)
        self._cbxComputer.setEnabled(True)
        self._btnAddComputer.setEnabled(True)
        self._btnRemoveComputer.setEnabled(True)
        self._btnTransfer.setEnabled(True)
        self._btnExit.setEnabled(True)