def initialize_context(self):

        reloading_layout = self.context_group.layout()

        if reloading_layout is None:
            reloading_layout = QVBoxLayout()
            self.context_group.setLayout(reloading_layout)
        else:
            while not reloading_layout.isEmpty():
                # Our first item is always the button
                item = reloading_layout.takeAt(0)
                self.output_grid_layout.removeItem(item)
                if item.widget():
                    item.widget().deleteLater()
                self.name_label = QLabel()

        button_layout = QGridLayout()

        var_button = QPushButton("Local values")
        var_button.clicked.connect(self.show_locals)
        button_layout.addWidget(var_button, 0, 0)

        func_button = QPushButton("Functions")
        func_button.clicked.connect(self.show_local_funcs)
        button_layout.addWidget(func_button, 0, 1)

        out_button = QPushButton("Outputs")
        out_button.clicked.connect(self.show_outs)
        button_layout.addWidget(out_button, 1, 0)

        del_button = QPushButton("Delete")
        del_button.clicked.connect(self.delete_organ)
        button_layout.addWidget(del_button, 1, 1)
        reloading_layout.addWidget(self.name_label)
        reloading_layout.addLayout(button_layout)
class MainWindow(QMainWindow):
   def __init__(self, client_socket, process_events_method):
      super().__init__()

      self.username = config.user["username"]
      self.client_socket = client_socket
      self.client_socket.recv_message.connect(self.recvMessage)
      self.process_events_method = process_events_method
      self.chats = {}
      self.send_on_enter = True

      self.initMenubar()
      self.initUI()

      for chat in config.chats:
         self.createChat(chat, config.chats[chat]["participants"])

   def initMenubar(self):
      self.createChatAction = QAction("&Create Chat", self)
      #self.exitAction.setShortcut("Ctrl+Q")
      self.createChatAction.triggered.connect(self.createChat)

      self.addFriendAction = QAction("&Add Friend", self)
      self.addFriendAction.triggered.connect(self.addFriend)

      self.menubar = self.menuBar()
      self.chatMenu = self.menubar.addMenu("&Chat")
      self.chatMenu.addAction(self.createChatAction)

      self.friendMenu = self.menubar.addMenu("&Friend")
      self.friendMenu.addAction(self.addFriendAction)

   def initUI(self):
      self.content = QWidget()

      self.hbox = QHBoxLayout(self.content)
      self.setCentralWidget(self.content)

      self.friend_list = QListWidget()
      self.friend_list.itemClicked.connect(self.friendClicked)

      self.message_scroll = QScrollArea()
      self.message_scroll.setWidgetResizable(True)
      #TODO have a setting to disable this
      self.message_scroll.verticalScrollBar().rangeChanged.connect(self.scrollBottom)

      self.message_input = MessageInput()
      self.message_input.sendMessage.connect(self.sendMessage)

      self.message_split = QSplitter(Qt.Vertical)
      self.message_split.addWidget(self.message_scroll)
      self.message_split.addWidget(self.message_input)

      self.main_split = QSplitter(Qt.Horizontal)
      self.main_split.addWidget(self.friend_list)
      self.main_split.addWidget(self.message_split)

      self.hbox.addWidget(self.main_split)

      self.show()

   def addFriend(self, username=None):
      if type(username) is bool:
         add_friend_dialog = AddFriendDialog(self.client_socket)
         add_friend_dialog.exec_()
         if add_friend_dialog.selected_user == None:
            return
         username = add_friend_dialog.selected_user
      self.chats[username] = {"participants":[username], "messages":[]}
      #TODO we should probably sanatize these to prevent directory manipulation
      friend = QListWidgetItem(QIcon(config.ICON_DIR + username + ".png"), username)
      self.friend_list.addItem(friend)

   def createChat(self, chat_name=None, participants=None):
      if type(chat_name) is bool:
         create_chat_dialog = CreateChatDialog()
         create_chat_dialog.exec_()
         if not create_chat_dialog.created_chat:
            return
         chat_name = create_chat_dialog.chat_name
         participants = create_chat_dialog.participants
      self.chats[chat_name] = {"participants":participants, "messages":[]}
      self.friend_list.addItem(QListWidgetItem(chat_name))

   def friendClicked(self, item):
      self.loadMessages(str(item.text()))

   def loadMessages(self, chat):
      #self.clearMessages()
      #TODO make the message history look pretty
      #TODO consider storing a message history for each chat and switch between when needed
      #TODO create a chat class and store the chat name as well as the participants there
      #TODO index message histories by chat name
      self.message_history = QVBoxLayout()
      self.message_history.setSpacing(0)
      self.message_history.setContentsMargins(0,0,0,0)
      self.message_history.insertStretch(-1, 1)
      self.message_history_container = QWidget()
      self.message_history_container.setLayout(self.message_history)
      self.message_scroll.setWidget(self.message_history_container)
      for message in self.chats[chat]["messages"]:
         self.drawMessage(message)

   def clearMessages(self):
      while not self.message_history.isEmpty():
         self.message_history.takeAt(0)

   def sendMessage(self):
      message = self.message_input.toPlainText().strip()
      chat = self.friend_list.selectedItems()[0].text()
      self.client_socket.sendMessage(message, chat, self.chats[chat]["participants"])
      print("Sending: %s to %s" % (message, chat))
      self.message_input.setText("")
      self.recvMessage(chat, {"sender":self.username, "message":message})

   def recvMessage(self, chat, message):
      self.chats[chat]["messages"].append(message)
      current_chat = self.friend_list.selectedItems()[0].text()
      if current_chat == chat:
         self.drawMessage(message)

   def drawMessage(self, message):
      #TODO add a timestamp to messages
      new_message = QLabel(message["sender"] + ':' + message["message"])
      self.message_history.addWidget(new_message)

   def scrollBottom(self):
      self.message_scroll.verticalScrollBar().setValue(self.message_scroll.verticalScrollBar().maximum())

   def disconnect(self):
      self.client_socket.disconnect()
Exemple #3
0
class RentingList(QWidget):
    def __init__(self, parent):
        super(RentingList, self).__init__()

        self.parent = parent

        self.setMaximumWidth(1000)

        self.current_theme = self.parent.current_theme
        self.current_font = self.parent.current_font
        self.current_sf = self.parent.current_sf

        if (self.current_theme == 'Dark'):
            self.darkTheme()
        elif (self.current_theme == 'Light'):
            self.lightTheme()
        else:
            self.classicTheme()

        self.requests = []

        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(30, 30, 30, 30)
        self.layout.setSpacing(10)
        self.layout.setAlignment(QtCore.Qt.AlignTop)
        self.setLayout(self.layout)

    def addRequests(self):
        self.requests = []

        while (not self.layout.isEmpty()):
            self.layout.removeWidget(self.layout.itemAt(0).widget())

        stats = self.parent.parent.sender.get_job_statuses()

        for job in stats:
            request = RentingRequest(self, job)
            self.requests.append(request)
            self.layout.addWidget(request, alignment=QtCore.Qt.AlignTop)

        if (len(self.requests) == 0):
            request = EmptyRequest(self)
            request.requestLabel.setText('You have no renting requests')
            self.requests.append(request)
            self.layout.addWidget(request, alignment=QtCore.Qt.AlignTop)

            return 0

        return len(self.requests)

    def darkTheme(self):
        self.setStyleSheet('background: rgb(69, 69, 69);\n'
                           'color: white;\n'
                           'border: 0px solid white;\n'
                           'margin: 0px;\n')

    def lightTheme(self):
        self.setStyleSheet('background: rgb(204, 204, 204);\n'
                           'color: white;\n'
                           'border: 0px solid black;\n')

    def classicTheme(self):
        self.setStyleSheet('background: rgb(0, 23, 37);\n'
                           'color: white;\n'
                           'border: 0px solid white;\n')
Exemple #4
0
class GodWidget(QWidget):
    '''
    "Our lord and savior, the holy child of window-shua, there is no
    widget above thee." - 6|6

    The highest level composed widget which contains layouts for
    organizing charts as well as other sub-widgets used to control or
    modify them.

    '''
    def __init__(

        self,
        parent=None,

    ) -> None:

        super().__init__(parent)

        self.hbox = QHBoxLayout(self)
        self.hbox.setContentsMargins(0, 0, 0, 0)
        self.hbox.setSpacing(6)
        self.hbox.setAlignment(Qt.AlignTop)

        self.vbox = QVBoxLayout()
        self.vbox.setContentsMargins(0, 0, 0, 0)
        self.vbox.setSpacing(2)
        self.vbox.setAlignment(Qt.AlignTop)

        self.hbox.addLayout(self.vbox)

        # self.toolbar_layout = QHBoxLayout()
        # self.toolbar_layout.setContentsMargins(0, 0, 0, 0)
        # self.vbox.addLayout(self.toolbar_layout)

        # self.init_timeframes_ui()
        # self.init_strategy_ui()
        # self.vbox.addLayout(self.hbox)

        self._chart_cache: dict[str, LinkedSplits] = {}
        self.linkedsplits: Optional[LinkedSplits] = None

        # assigned in the startup func `_async_main()`
        self._root_n: trio.Nursery = None

        self._widgets: dict[str, QWidget] = {}
        self._resizing: bool = False

    # def init_timeframes_ui(self):
    #     self.tf_layout = QHBoxLayout()
    #     self.tf_layout.setSpacing(0)
    #     self.tf_layout.setContentsMargins(0, 12, 0, 0)
    #     time_frames = ('1M', '5M', '15M', '30M', '1H', '1D', '1W', 'MN')
    #     btn_prefix = 'TF'

    #     for tf in time_frames:
    #         btn_name = ''.join([btn_prefix, tf])
    #         btn = QtWidgets.QPushButton(tf)
    #         # TODO:
    #         btn.setEnabled(False)
    #         setattr(self, btn_name, btn)
    #         self.tf_layout.addWidget(btn)

    #     self.toolbar_layout.addLayout(self.tf_layout)

    # XXX: strat loader/saver that we don't need yet.
    # def init_strategy_ui(self):
    #     self.strategy_box = StrategyBoxWidget(self)
    #     self.toolbar_layout.addWidget(self.strategy_box)

    def set_chart_symbol(
        self,
        symbol_key: str,  # of form <fqsn>.<providername>
        linkedsplits: LinkedSplits,  # type: ignore

    ) -> None:
        # re-sort org cache symbol list in LIFO order
        cache = self._chart_cache
        cache.pop(symbol_key, None)
        cache[symbol_key] = linkedsplits

    def get_chart_symbol(
        self,
        symbol_key: str,

    ) -> LinkedSplits:  # type: ignore
        return self._chart_cache.get(symbol_key)

    async def load_symbol(
        self,
        providername: str,
        symbol_key: str,
        loglevel: str,
        reset: bool = False,

    ) -> trio.Event:
        '''
        Load a new contract into the charting app.

        Expects a ``numpy`` structured array containing all the ohlcv fields.

        '''
        # our symbol key style is always lower case
        symbol_key = symbol_key.lower()

        # fully qualified symbol name (SNS i guess is what we're making?)
        fqsn = '.'.join([symbol_key, providername])

        linkedsplits = self.get_chart_symbol(fqsn)

        order_mode_started = trio.Event()

        if not self.vbox.isEmpty():

            # XXX: this is CRITICAL especially with pixel buffer caching
            self.linkedsplits.hide()
            self.linkedsplits.unfocus()

            # XXX: pretty sure we don't need this
            # remove any existing plots?
            # XXX: ahh we might want to support cache unloading..
            # self.vbox.removeWidget(self.linkedsplits)

        # switching to a new viewable chart
        if linkedsplits is None or reset:
            from ._display import display_symbol_data

            # we must load a fresh linked charts set
            linkedsplits = LinkedSplits(self)

            # spawn new task to start up and update new sub-chart instances
            self._root_n.start_soon(
                display_symbol_data,
                self,
                providername,
                symbol_key,
                loglevel,
                order_mode_started,
            )

            self.set_chart_symbol(fqsn, linkedsplits)
            self.vbox.addWidget(linkedsplits)

            linkedsplits.show()
            linkedsplits.focus()
            await trio.sleep(0)

        else:
            # symbol is already loaded and ems ready
            order_mode_started.set()

            # TODO:
            # - we'll probably want per-instrument/provider state here?
            #   change the order config form over to the new chart

            # XXX: since the pp config is a singleton widget we have to
            # also switch it over to the new chart's interal-layout
            # self.linkedsplits.chart.qframe.hbox.removeWidget(self.pp_pane)
            chart = linkedsplits.chart

            # chart is already in memory so just focus it
            linkedsplits.show()
            linkedsplits.focus()
            linkedsplits.graphics_cycle()
            await trio.sleep(0)

            # resume feeds *after* rendering chart view asap
            chart.resume_all_feeds()

            # TODO: we need a check to see if the chart
            # last had the xlast in view, if so then shift so it's
            # still in view, if the user was viewing history then
            # do nothing yah?
            chart.default_view()

        self.linkedsplits = linkedsplits
        symbol = linkedsplits.symbol
        if symbol is not None:
            self.window.setWindowTitle(
                f'{symbol.front_fqsn()} '
                f'tick:{symbol.tick_size}'
            )

        return order_mode_started

    def focus(self) -> None:
        '''
        Focus the top level widget which in turn focusses the chart
        ala "view mode".

        '''
        # go back to view-mode focus (aka chart focus)
        self.clearFocus()
        self.linkedsplits.chart.setFocus()

    def resizeEvent(self, event: QtCore.QEvent) -> None:
        '''
        Top level god widget resize handler.

        Where we do UX magic to make things not suck B)

        '''
        if self._resizing:
            return

        self._resizing = True

        log.info('God widget resize')
        for name, widget in self._widgets.items():
            widget.on_resize()

        self._resizing = False
Exemple #5
0
class LeasingList(QWidget):
    def __init__(self, parent):
        super(LeasingList, self).__init__()

        self.parent = parent

        self.setMaximumWidth(1000)

        self.current_theme = self.parent.current_theme
        self.current_font = self.parent.current_font
        self.current_sf = self.parent.current_sf

        if (self.current_theme == 'Dark'):
            self.darkTheme()
        elif (self.current_theme == 'Light'):
            self.lightTheme()
        else:
            self.classicTheme()

        self.requests = []

        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(30, 30, 30, 50)
        self.layout.setSpacing(10)
        self.layout.setAlignment(QtCore.Qt.AlignTop)
        self.setLayout(self.layout)

    def addRequests(self):
        self.requests = []

        while (not self.layout.isEmpty()):
            self.layout.removeWidget()

        requests = self.parent.parent.receiver.get_job_notifications()

        for r in requests:
            request = LeasingRequest(self)
            request.orderId = r[0]
            request.renterUserName = r[1]
            request.jobId = r[2]
            request.jobDesc = r[3]
            request.jobMode = r[4]
            request.status = r[5]
            request.price = r[6]

            request.setRenter(request.renterUserName)

            self.requests.append(request)
            self.layout.addWidget(request)

        if (len(self.requests) == 0):
            request = EmptyRequest(self)
            request.requestLabel.setText('You have no leasing requests')
            self.requests.append(request)
            self.layout.addWidget(request, alignment=QtCore.Qt.AlignTop)

            return 0

        return len(self.requests)

    def darkTheme(self):
        self.setStyleSheet('background: rgb(69, 69, 69);\n'
                           'color: white;\n'
                           'border: 0px solid white;\n')

    def lightTheme(self):
        self.setStyleSheet('background: rgb(204, 204, 204);\n'
                           'color: white;\n'
                           'border: 0px solid black;\n')

    def classicTheme(self):
        self.setStyleSheet('background: rgb(0, 23, 37);\n'
                           'color: white;\n'
                           'border: 0px solid white;\n')