Added:
trunk/profit/lib/widgets/infobar.py
- copied, changed from r316, /trunk/profit/lib/widgets/filterbar.py
trunk/profit/lib/widgets/ui_infobar.ui (contents, props changed)
trunk/profit/models/executions.py (contents, props changed)
trunk/profit/models/strategy.py (contents, props changed)
Modified:
trunk/profit/session/__init__.py
trunk/profit/strategy/builder.py
trunk/profit/strategydesigner/main.py
trunk/profit/workbench/executionsdisplay.py
trunk/profit/workbench/strategydisplay.py
trunk/profit/workbench/widgets/ui_executionsdisplay.ui
trunk/profit/workbench/widgets/ui_strategydisplay.ui
trunk/profit/workbench/widgets/ui_tickerdisplay.ui
Log:
Continued replacement of QStandardItem subclasses.
Copied: trunk/profit/lib/widgets/infobar.py (from r316,
/trunk/profit/lib/widgets/filterbar.py)
==============================================================================
--- /trunk/profit/lib/widgets/filterbar.py (original)
+++ trunk/profit/lib/widgets/infobar.py Tue Aug 5 23:24:40 2008
@@ -5,14 +5,14 @@
# Distributed under the terms of the GNU General Public License v2
from PyQt4.QtCore import pyqtSignature
-from PyQt4.QtGui import QWidget
+from PyQt4.QtGui import QFrame
from profit.lib import Signals
-from profit.lib.widgets.ui_filterbar import Ui_FilterBar
+from profit.lib.widgets.ui_infobar import Ui_InfoBar
-class FilterBar(QWidget, Ui_FilterBar):
- """ Widget with filter line edit and clear button.
+class InfoBar(QFrame, Ui_InfoBar):
+ """ Widget with info label and hide button.
"""
def __init__(self, parent=None):
@@ -20,21 +20,5 @@
@param parent ancestor of this widget
"""
- QWidget.__init__(self, parent)
+ QFrame.__init__(self, parent)
self.setupUi(self)
-
- @pyqtSignature('')
- def on_clearButton_clicked(self):
- """ signal handler called when clear button is pressed
-
- @return None
- """
- self.filterEdit.clear()
- self.filterEdit.emit(Signals.editingFinished)
-
- def on_filterEdit_textChanged(self, text):
- """ signal handler called when line edit text changed
-
- @param text current value of line edit as QString instance
- @return None
- """
Added: trunk/profit/lib/widgets/ui_infobar.ui
==============================================================================
--- (empty file)
+++ trunk/profit/lib/widgets/ui_infobar.ui Tue Aug 5 23:24:40 2008
@@ -0,0 +1,82 @@
+<ui version="4.0" >
+ <class>InfoBar</class>
+ <widget class="QFrame" name="InfoBar" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>486</width>
+ <height>58</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout" >
+ <item>
+ <widget class="QWidget" native="1" name="widget" />
+ </item>
+ <item>
+ <spacer name="horizontalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>337</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="barHelp" >
+ <property name="text" >
+ <string>Information</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="barClose" >
+ <property name="text" >
+ <string/>
+ </property>
+ <property name="icon" >
+ <iconset resource="profit.qrc" >
+
<normaloff>:/images/icons/fileclose.png</normaloff>:/images/icons/fileclose.png</iconset>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="profit.qrc" />
+ </resources>
+ <connections>
+ <connection>
+ <sender>barClose</sender>
+ <signal>clicked()</signal>
+ <receiver>InfoBar</receiver>
+ <slot>hide()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>23</x>
+ <y>28</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>242</x>
+ <y>28</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
Added: trunk/profit/models/executions.py
==============================================================================
--- (empty file)
+++ trunk/profit/models/executions.py Tue Aug 5 23:24:40 2008
@@ -0,0 +1,170 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright 2007 Troy Melhase <tr...@gci.net>
+# Distributed under the terms of the GNU General Public License v2
+
+from time import strftime, strptime
+
+from PyQt4.QtCore import Qt, QModelIndex, QVariant, QString
+from profit.lib import valueAlign
+from profit.models import BasicItem, BasicItemModel
+
+
+class ExecutionsModel(BasicItemModel):
+ """
+
+ """
+ def __init__(self, session=None, parent=None):
+ BasicItemModel.__init__(self, RootExecutionsItem(), parent)
+ self.symbolIcon = lambda x:None
+ self.session = session
+ if session is not None:
+ session.registerMeta(self)
+
+ def data(self, index, role):
+ """
+
+ """
+ if not index.isValid():
+ return QVariant()
+ item = index.internalPointer()
+ data = QVariant()
+ column = index.column()
+ if role == Qt.DecorationRole and column==2:
+ sym = item.symbol()
+ ico = self.symbolIcon(sym)
+ data = QVariant(ico)
+ elif role in (Qt.DisplayRole, Qt.ToolTipRole):
+ data = QVariant(item[column])
+ elif role in (Qt.TextAlignmentRole, ):
+ try:
+ float(item[column])
+ data = QVariant(valueAlign)
+ except (ValueError, ):
+ pass
+ return data
+
+ def findItem(self, orderId):
+ """ Returns the item for the given contract, or None.
+
+ """
+ items = self.invisibleRootItem.children
+ try:
+ return [i for i in items if
i.message.execution.m_orderId==orderId][0]
+ except (IndexError, ):
+ pass
+
+ def on_session_ExecDetails(self, message):
+ """ Adds a status row if the contract is known to the model.
+
+ """
+ item = self.findItem(message.execution.m_orderId)
+ if not item:
+ root = self.invisibleRootItem
+ item = ExecutionsItem.fromMessage(message, root)
+ root.append(item)
+ item.append(ExecutionsItem.fromMessage(message, item))
+ item.update(message)
+ self.reset()
+
+
+dayFormatOut = '%a %d %b %Y'
+dayFormatIn = '%Y%m%d'
+
+
+def messageDate(message):
+ """ Extracts and formats the date from an execution details message.
+
+ @param message message instance
+ @return formatted date as string
+ """
+ datetime = message.execution.m_time
+ datepart = datetime.split()[0]
+ return strftime(dayFormatOut, strptime(datepart, dayFormatIn))
+
+
+def messageTime(message):
+ """ Extracts the time from an execution details message.
+
+ @param message message instance
+ @return time as string
+ """
+ datetime = message.execution.m_time
+ timepart = datetime.split()[1]
+ return timepart
+
+
+class ExecutionsItem(BasicItem):
+ """ Base class for items in the executions model.
+
+ """
+ columnLookups = [
+ ('Action', lambda m:m.execution.m_side),
+ ('Quantity', lambda m:m.execution.m_shares),
+ ('Underlying', lambda m:m.contract.m_symbol),
+ ('Price', lambda m:m.execution.m_price),
+ ('Currency', lambda m:m.contract.m_currency),
+ ('Exchange', lambda m:m.execution.m_exchange),
+ ('Date', messageDate),
+ ('Time', messageTime),
+ ('Id', lambda m:m.execution.m_permId),
+ ('Order Reference', lambda m:m.execution.m_orderId),
+ ]
+
+ def __init__(self, data, parent=None, message=None):
+ BasicItem.__init__(self, data, parent)
+ self.message = message
+
+ @classmethod
+ def fromMessage(cls, message, parent):
+ """ New instance from message values
+
+ @param cls class object
+ @param message ib.opt.message object
+ @param parent parent of this item
+ @return new instance of cls
+ """
+ values = []
+ for label, lookup in cls.columnLookups:
+ try:
+ value = lookup(message)
+ except (AttributeError, ):
+ value = ''
+ values.append(value)
+ return cls(values, parent, message)
+
+ def symbol(self):
+ """ Returns the symbol for this item or ''
+
+ """
+ try:
+ return self.message.contract.m_symbol
+ except (AttributeError, ):
+ return ''
+
+ def update(self, message):
+ """ Update the item with values from a message.
+
+ @param message ib.opt.message object
+ @return None
+ """
+ for column, (label, lookup) in enumerate(self.columnLookups):
+ try:
+ self[column] = lookup(message)
+ except (AttributeError, ):
+ pass
+
+
+class RootExecutionsItem(ExecutionsItem):
+ """ Executions model item with automatic values (for horizontal
headers).
+
+ """
+ def __init__(self):
+ ExecutionsItem.__init__(self, self.horizontalLabels())
+
+ def horizontalLabels(self):
+ """ Generates list of horizontal header values.
+
+ """
+ return map(QVariant, [label for label, lookup in
self.columnLookups])
Added: trunk/profit/models/strategy.py
==============================================================================
--- (empty file)
+++ trunk/profit/models/strategy.py Tue Aug 5 23:24:40 2008
@@ -0,0 +1,162 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright 2007 Troy Melhase <tr...@gci.net>
+# Distributed under the terms of the GNU General Public License v2
+
+from PyQt4.QtCore import Qt, QModelIndex, QVariant, QSize, QString
+from profit.lib import Signals, valueAlign, SettingsHandler
+from profit.models import BasicItem, BasicItemModel
+
+
+class StrategyModel(BasicItemModel, SettingsHandler):
+ """ Model for strategies.
+
+ """
+ def __init__(self, session=None, parent=None):
+ """ Initializer.
+
+ """
+ BasicItemModel.__init__(self, RootStrategyItem(), parent)
+ self.symbolIcon = lambda x:None
+ self.iconMap = {}
+ self.session = session
+ if session is not None:
+ session.registerMeta(self)
+ self.readSettings()
+
+ def data(self, index, role=Qt.DisplayRole):
+ """ Framework hook to retreive data stored at index for given role.
+
+ @param index QModelIndex instance
+ @param role Qt.DisplayRole flags
+ @return QVariant instance
+ """
+ data = QVariant()
+ if not index.isValid():
+ return data
+ col = index.column()
+ item = index.internalPointer()
+ if role == Qt.DisplayRole:
+ if col in (item.tickersIdx, item.runnersIdx):
+ data = 'active' if item[col] else 'inactive'
+ elif col == item.filenameIdx:
+ data = item[item.filenameIdx]
+ elif role == Qt.DecorationRole:
+ if col in (item.tickersIdx, item.runnersIdx):
+ data = self.iconMap.get(item[col], QVariant())
+ elif role == Qt.EditRole:
+ data = item[col]
+ elif role == Qt.CheckStateRole:
+ if col in (item.tickersIdx, item.runnersIdx):
+ data = (item[col] and Qt.Checked) or Qt.Unchecked
+ elif role == Qt.SizeHintRole:
+ data = QSize(0, 30)
+ data = QVariant(data)
+ return data
+
+ def decodeRows(self, rows):
+ """ Yields a list of items for each row.
+
+ """
+ for row in rows:
+ yield [False, False, row.get('filename', '')]
+
+ def flags(self, index):
+ if not index.isValid():
+ return Qt.ItemIsEnabled
+ col = index.column()
+ item = index.internalPointer()
+ flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable
+ if col == item.tickersIdx:
+ flags |= Qt.ItemIsUserCheckable | Qt.ItemIsEditable
+ elif col == item.runnersIdx:
+ flags |= Qt.ItemIsUserCheckable | Qt.ItemIsEditable
+ elif col == item.filenameIdx:
+ if 0: # item[item.tickersIdx] or item[item.runnersIdx]:
+ flags = Qt.NoItemFlags
+ else:
+ flags |= Qt.ItemIsSelectable | Qt.ItemIsEditable
+ return flags
+
+ def readSettings(self):
+ """ Loads saved strategies directly into the model.
+
+ """
+ root = self.invisibleRootItem
+ settings = self.settings
+ settings.beginGroup(settings.keys.strategy)
+ for row in self.decodeRows(settings.valueLoad('strategies', [])):
+ root.append(StrategyItem(row, root))
+ settings.endGroup()
+ self.reset()
+
+ def saveSettings(self):
+ """
+
+ """
+ settings = self.settings
+ settings.beginGroup(settings.keys.strategy)
+ settings.setValueDump('strategies',
self.strategyModel.encodeRows())
+ settings.endGroup()
+
+
+ def setData(self, index, value, role=Qt.EditRole):
+ """ Framework hook to set value at the given index for the role.
+
+ """
+ if not index.isValid():
+ return False
+ item = index.internalPointer()
+ col = index.column()
+ if col in (item.tickersIdx, item.runnersIdx):
+ value = item[col] = value.toBool()
+ rowdict = {'active':value, 'filename':item[item.filenameIdx]}
+ self.emit(Signals.strategy.requestActivate,
+ rowdict, value)
+ elif col in (item.filenameIdx, ):
+ item[col] = str(value.toString())
+ else:
+ return False
+ self.emit(Signals.dataChanged, index, index)
+ return True
+
+ def removeRow(self, row, parent=QModelIndex()):
+ root = self.invisibleRootItem
+ self.beginRemoveRows(parent, row, row)
+ result = root.children.pop(row)
+ self.endRemoveRows()
+ return bool(result)
+
+ def appendRowFromData(self, filename='', **kwds):
+ root = self.invisibleRootItem
+ row = root.childCount()
+ self.beginInsertRows(QModelIndex(), row, row)
+ root.append(StrategyItem([False, False, filename], root))
+ self.endInsertRows()
+
+
+class StrategyItem(BasicItem):
+ """ Base class for items in the strategy model.
+
+ """
+ columnIndexes = tickersIdx, runnersIdx, filenameIdx = range(3)
+ columnLookups = [
+ ('Tickers', None),
+ ('Runners', None),
+ ('Filename', None),
+ ]
+
+
+class RootStrategyItem(StrategyItem):
+ """ Strategy model item with automatic values (for horizontal headers).
+
+ """
+ def __init__(self):
+ StrategyItem.__init__(self, self.horizontalLabels())
+
+ def horizontalLabels(self):
+ """ Generates list of horizontal header values.
+
+ """
+ return map(QVariant, [label for label, lookup in
self.columnLookups])
Modified: trunk/profit/session/__init__.py
==============================================================================
--- trunk/profit/session/__init__.py (original)
+++ trunk/profit/session/__init__.py Tue Aug 5 23:24:40 2008
@@ -15,17 +15,17 @@
from ib.opt import ibConnection
from ib.opt.message import messageTypeNames
-from profit.lib import logging
-from profit.lib import Signals
+from profit.lib import Signals, logging, instance
+from profit.models.executions import ExecutionsModel
+from profit.models.orders import OrdersModel
+from profit.models.portfolio import PortfolioModel
+from profit.models.strategy import StrategyModel
+from profit.models.tickers import TickersModel
from profit.session import collection
from profit.session.savethread import SaveThread
from profit.session.requestthread import RequestThread
from profit.strategy.builder import SessionStrategyBuilder
-from profit.models.orders import OrdersModel
-from profit.models.portfolio import PortfolioModel
-from profit.models.tickers import TickersModel
-
class DataMaps(object):
def __init__(self, session):
@@ -39,8 +39,10 @@
class DataModels(object):
def __init__(self, session):
+ self.executions = ExecutionsModel(session)
self.orders = OrdersModel(session)
self.portfolio = PortfolioModel(session)
+ self.strategy = StrategyModel(session)
self.tickers = TickersModel(session)
@@ -60,8 +62,11 @@
self.savedLength = 0
self.maps = DataMaps(self)
self.models = DataModels(self)
+ app = instance()
self.connect(self.strategy, Signals.contract.created,
self, Signals.contract.created)
+ self.connect(self.models.strategy,
Signals.strategy.requestActivate,
+ app, Signals.strategy.requestActivate)
def __str__(self):
""" x.__str__() <==> str(x)
@@ -426,10 +431,10 @@
def testContract(self, orderId, price=30.0, symbol='MSFT',
- orderType='MKT'):
+ orderType='MKT', action='SELL'):
strategy = self.strategy
contract = strategy.makeContract(symbol)
- order = strategy.makeOrder(action='SELL',
+ order = strategy.makeOrder(action=action,
orderType=orderType,
totalQuantity='100',
openClose='O',
Modified: trunk/profit/strategy/builder.py
==============================================================================
--- trunk/profit/strategy/builder.py (original)
+++ trunk/profit/strategy/builder.py Tue Aug 5 23:24:40 2008
@@ -125,6 +125,7 @@
self.emit(Signals.createdTicker, item['tickerId'], item)
def requestActivation(self, strategy, activate=False):
+ print '## ding ding requestActivation', strategy
filename = strategy.get('filename', None)
if activate:
if filename:
Modified: trunk/profit/strategydesigner/main.py
==============================================================================
--- trunk/profit/strategydesigner/main.py (original)
+++ trunk/profit/strategydesigner/main.py Tue Aug 5 23:24:40 2008
@@ -14,7 +14,7 @@
from PyQt4.QtGui import QSizePolicy, QSpinBox, QStandardItem
from PyQt4.QtGui import QStandardItemModel, QToolBar
-from profit.lib import series
+from profit import series
from profit.lib import defaults
from profit.lib import Settings, Signals
from profit.lib.widgets.syspathdialog import SysPathDialog
Modified: trunk/profit/workbench/executionsdisplay.py
==============================================================================
--- trunk/profit/workbench/executionsdisplay.py (original)
+++ trunk/profit/workbench/executionsdisplay.py Tue Aug 5 23:24:40 2008
@@ -4,161 +4,13 @@
# Copyright 2007 Troy Melhase <tr...@gci.net>
# Distributed under the terms of the GNU General Public License v2
-from time import strftime, strptime
-
-from PyQt4.QtCore import QAbstractTableModel, QVariant, Qt
from PyQt4.QtGui import QFrame
-from profit.lib import BasicHandler, Signals, Slots, makeCheckNames,
valueAlign
+from profit.lib import BasicHandler
from profit.lib.gui import symbolIcon
from profit.workbench.widgets.ui_executionsdisplay import
Ui_ExecutionsDisplay
-dayFormatOut = '%a %d %b %Y'
-dayFormatIn = '%Y%m%d'
-
-
-def messageDate(message):
- """ Extracts and formats the date from an execution details message.
-
- @param message message instance
- @return formatted date as string
- """
- datetime = message.execution.m_time
- datepart = datetime.split()[0]
- return strftime(dayFormatOut, strptime(datepart, dayFormatIn))
-
-
-def messageTime(message):
- """ Extracts the time from an execution details message.
-
- @param message message instance
- @return time as string
- """
- datetime = message.execution.m_time
- timepart = datetime.split()[1]
- return timepart
-
-
-class ExecutionsTableModel(QAbstractTableModel):
- """ Data model for execution details messages table.
-
- """
- columnTitles = [
- 'Action', 'Quantity', 'Underlying', 'Price', 'Currency',
- 'Exchange', 'Date', 'Time', 'Id', 'Order Reference',
- ]
- dataExtractors = {
- 0:lambda m:m.execution.m_side,
- 1:lambda m:m.execution.m_shares,
- 2:lambda m:m.contract.m_symbol,
- 3:lambda m:m.execution.m_price,
- 4:lambda m:m.contract.m_currency,
- 5:lambda m:m.execution.m_exchange,
- 6:messageDate,
- 7:messageTime,
- 8:lambda m:m.execution.m_permId,
- 9:lambda m:m.execution.m_orderId,
- }
- alignments = {
- 1:valueAlign,
- 3:valueAlign,
- 6:valueAlign,
- 7:valueAlign,
- 8:valueAlign,
- 9:valueAlign,
- }
-
- def __init__(self, session, parent=None):
- """ Constructor.
-
- @param session Session instance
- @param parent ancestor object
- """
- QAbstractTableModel.__init__(self, parent)
- self.setSession(session)
-
-
- def setSession(self, session):
- """ Associates this model with a session.
-
- @param session Session instance
- @return None
- """
- isExecMessage = makeCheckNames('ExecDetails')
- msgs = enumerate((msg for time, msg in session.messages))
- self.messageIndexes = [idx for idx, msg in msgs if
isExecMessage(msg)]
- self.session = session
- self.messages = session.messages
- session.registerMeta(self)
-
- def on_session_ExecDetails(self, message):
- """ Signal handler for incoming execution details messages.
-
- @param message ExecDetails message instance
- @return None
- """
-
self.messageIndexes.append(self.session.messagesBare.index(message))
- self.emit(Signals.layoutChanged)
-
- def data(self, index, role):
- """ Framework hook to determine data stored at index for given
role.
-
- @param index QModelIndex instance
- @param role Qt.DisplayRole flags
- @return QVariant instance
- """
- if not index.isValid():
- return QVariant()
- row = index.row()
- col = index.column()
- msgindex = self.messageIndexes[row]
- mtime, message = self.messages[msgindex]
- if role == Qt.DecorationRole and col == 2:
- return QVariant(symbolIcon(message.contract.m_symbol))
- elif role == Qt.TextAlignmentRole:
- try:
- val = QVariant(self.alignments[col])
- except (KeyError, ):
- val = QVariant()
- return val
- elif role != Qt.DisplayRole:
- return QVariant()
- try:
- val = QVariant(self.dataExtractors[col](message))
- except (KeyError, ):
- val = QVariant()
- return val
-
- def headerData(self, section, orientation, role):
- """ Framework hook to determine header data.
-
- @param section integer specifying header (e.g., column number)
- @param orientation Qt.Orientation value
- @param role Qt.DisplayRole flags
- @return QVariant instance
- """
- if orientation == Qt.Horizontal and role == Qt.DisplayRole:
- return QVariant(self.columnTitles[section])
- return QVariant()
-
- def rowCount(self, parent=None):
- """ Framework hook to determine data model row count.
-
- @param parent ignored
- @return number of rows (number of execution details messages)
- """
- return len(self.messageIndexes)
-
- def columnCount(self, parent=None):
- """ Framework hook to determine data model column count.
-
- @param parent ignored
- @return number of columns (see columnTitles)
- """
- return len(self.columnTitles)
-
-
class ExecutionsDisplay(QFrame, Ui_ExecutionsDisplay, BasicHandler):
""" Combines a filter bar and an exec details table.
@@ -171,7 +23,6 @@
QFrame.__init__(self, parent)
self.setupUi(self)
self.requestSession()
- self.executionsTable.verticalHeader().hide()
def setSession(self, session):
""" Configures this instance for a session.
@@ -180,11 +31,6 @@
@return None
"""
self.session = session
- try:
- model = session.executionsDisplayModel
- except (AttributeError, ):
- model = session.executionsDisplayModel = \
- ExecutionsTableModel(session)
- self.executionsTable.setModel(model)
- session.register(self.executionsTable, 'ExecDetails',
- Slots.scrollToBottom)
+ model = session.models.executions
+ model.symbolIcon = symbolIcon
+ self.executionsView.setModel(model)
Modified: trunk/profit/workbench/strategydisplay.py
==============================================================================
--- trunk/profit/workbench/strategydisplay.py (original)
+++ trunk/profit/workbench/strategydisplay.py Tue Aug 5 23:24:40 2008
@@ -10,139 +10,82 @@
from PyQt4.QtGui import (QFrame, QIcon, QMessageBox, QPushButton,
QItemDelegate, QStandardItem,
- QStandardItemModel, QFileDialog, )
+ QFileDialog, )
from profit.lib import defaults, logging
from profit.lib import BasicHandler, Signals, DataRoles, instance
from profit.lib.gui import StandardItem
from profit.workbench.widgets.ui_strategydisplay import Ui_StrategyDisplay
-## This model can be (almost) easily replaced with an abstract item
-## model. Use profit.models.BasicItemModel.
-
-class StrategyDisplayModel(QStandardItemModel):
- """ Model for strategy display table.
-
- This model doesn't make any attempt to identify a strategy by a
- unique key. The user can add the same strategy file multiple
- times via a view, yet this class only distinguishes by
- (transitory) row numbers.
- """
- labels = ['Active', 'Status', 'File', ]
-
- def __init__(self, session, view, parent=None):
- QStandardItemModel.__init__(self, parent)
- self.session = session
- self.activeIcon = (view.activeIcon if view else QIcon())
- self.inactiveIcon = (view.inactiveIcon if view else QIcon())
- self.setHorizontalHeaderLabels(self.labels)
-
- def appendRowFromData(self, **kwds):
- """ Create and append row based on model data and method
parameters.
-
- """
- items = self.makeRowItems(**kwds)
- self.appendRow(items)
-
- def rowToDict(self, row):
- """
-
- """
- return {
- 'active':self.item(row, 0).checkState(),
- 'filename':str(self.item(row, 2).text()),
- }
-
- def encodeRows(self):
- """ Encode model items as dictionaries.
-
- """
- return [self.rowToDict(i) for i in range(self.rowCount())]
-
- def decodeRows(self, rows):
- """ Yields a list of items for each row.
-
- """
- for row in rows:
- yield self.makeRowItems(icon=self.inactiveIcon,
- filename=row['filename'])
-
- def makeRowItems(self, **kwds):
- """
-
- """
- return [
- StandardItem(checkable=True, checkState=Qt.Unchecked,
- enabled=True, alignment=Qt.AlignCenter),
- StandardItem('inactive', icon=kwds.get('icon', QIcon())),
- StandardItem(kwds.get('filename', '')),
- ]
-
class StrategyDisplay(QFrame, Ui_StrategyDisplay, BasicHandler):
- """
+ """ StrategyDisplay -> a nice panel to manage strategies.
"""
confirmActivateKey = 'confirmActivate'
def __init__(self, parent=None):
+ """ Initializer.
+
+ @param parent ancestor of this object
+ """
QFrame.__init__(self, parent)
self.setupUi(self)
+ self.setupWidgets()
+ self.requestSession()
+
+ def setupWidgets(self):
self.inactiveIcon = QIcon(':/images/icons/connect_no.png')
self.activeIcon = QIcon(':/images/icons/connect_established.png')
settings = self.settings
settings.beginGroup(settings.keys.strategy)
confirm = settings.value(self.confirmActivateKey, True)
- self.confirmActivate.setCheckState(Qt.Checked if confirm.toBool()
- else Qt.Unchecked)
+ confirmActivate = Qt.Checked if confirm.toBool() else Qt.Unchecked
+ self.confirmActivate.setCheckState(confirmActivate)
settings.endGroup()
- self.requestSession()
- def setSession(self, session):
- """
- """
+ def on_strategyView_selectionChanged(self, selected, deselected):
+ loaded = any(i.internalPointer().data[0] or
+ i.internalPointer().data[1]
+ for i in selected.indexes())
+ self.editButton.setEnabled(not loaded)
+ self.removeButton.setEnabled(not loaded)
+
+ def setSession(self, session):
self.session = session
+ model = session.models.strategy
+ model.iconMap = {False:self.inactiveIcon, True:self.activeIcon}
+ self.strategyView.setModel(model)
+ ## this has to happen after the model is set, not during init.
connect = self.connect
- try:
- self.strategyModel = model = session.strategy.displayModel
- except (AttributeError, ):
- self.strategyModel = model = session.strategy.displayModel = \
- StrategyDisplayModel(session, self)
- self.readSettings()
- view = self.strategyTable
- view.setModel(model)
- view.verticalHeader().hide()
- view.resizeColumnsToContents()
- connect(model, Signals.itemChanged,
- self.on_strategyTable_itemChanged)
- connect(view.selectionModel(), Signals.selectionChanged,
- self.on_strategyTable_selectionChanged)
- connect(self, Signals.strategy.requestActivate,
- instance(), Signals.strategy.requestActivate)
-
- def on_strategyTable_doubleClicked(self, index):
- """
+ connect(self.strategyView.selectionModel(),
+ Signals.selectionChanged,
+ self.on_strategyView_selectionChanged)
+# connect(self, Signals.strategy.requestActivate,
+# instance(), Signals.strategy.requestActivate)
- """
- # don't check item state because the click function does
- # nothing if the button is disabled.
- self.editButton.click()
- def on_strategyTable_selectionChanged(self, selected, deselected):
+ def __on_strategyView_doubleClicked(self, index):
"""
"""
- try:
- item = self.strategyModel.itemFromIndex(selected.indexes()[0])
- except (IndexError, ):
- pass
+ if (not index.isValid()) or (index.column() != 2):
+ return
+ row = index.internalPointer().data
+ if not (row[0] or row[1]):
+ self.editButton.click()
+
+ def __on_strategyView_clicked(self, index):
+ if not index.isValid():
+ active = False
else:
- active = item.checkState()
- self.editButton.setEnabled(not active)
- self.removeButton.setEnabled(not active)
+ row = index.internalPointer().data
+ active = row[0] or row[1]
+ self.editButton.setEnabled(not active)
+ self.removeButton.setEnabled(not active)
- def on_strategyTable_itemChanged(self, item):
+ def __on_strategyTable_itemChanged(self, item):
"""
"""
@@ -199,19 +142,17 @@
"""
from profit.strategydesigner.main import StrategyDesigner
- indexes = self.strategyTable.selectedIndexes()
+ indexes = self.strategyView.selectedIndexes()
try:
- row = [i.row() for i in indexes if i.isValid()][0]
+ index = [i for i in indexes if i.isValid()][0]
except (IndexError, ):
pass
else:
- item = self.strategyModel.item(row, 0)
- other = self.strategyModel.item(row, 2)
- filename = other.text()
+ item = index.internalPointer()
+ filename = item[item.filenameIdx]
win = StrategyDesigner(filename=filename, parent=self)
win.show()
-
@pyqtSignature('')
def on_loadButton_clicked(self):
"""
@@ -219,24 +160,25 @@
"""
fn = QFileDialog.getOpenFileName(self, 'Select Strategy File', '')
if fn:
- self.strategyModel.appendRowFromData(filename=fn,
- icon=self.inactiveIcon)
- self.strategyTable.resizeColumnsToContents()
- self.saveSettings()
+ view = self.strategyView
+ view.model().appendRowFromData(filename=fn)
+ ##self.saveSettings()
@pyqtSignature('')
def on_removeButton_clicked(self):
"""
"""
- indexes = self.strategyTable.selectedIndexes()
+ view = self.strategyView
+ model = view.model()
+ indexes = view.selectedIndexes()
rows = set(i.row() for i in indexes if i.isValid())
for row in reversed(sorted(list(rows))):
- self.strategyModel.takeRow(row)
- self.strategyTable.clearSelection()
+ model.removeRow(row)
+ view.clearSelection()
self.editButton.setEnabled(False)
self.removeButton.setEnabled(False)
- self.saveSettings()
+# self.saveSettings()
def readSettings(self):
""" Load saved strategies and send them to the model.
@@ -257,3 +199,64 @@
settings.beginGroup(settings.keys.strategy)
settings.setValueDump('strategies',
self.strategyModel.encodeRows())
settings.endGroup()
+
+
+class StrategyDisplayModel:
+ """ Model for strategy display table.
+
+ This model doesn't make any attempt to identify a strategy by a
+ unique key. The user can add the same strategy file multiple
+ times via a view, yet this class only distinguishes by
+ (transitory) row numbers.
+ """
+ labels = ['Active', 'Status', 'File', ]
+
+ def __init__(self, session, view, parent=None):
+ QStandardItemModel.__init__(self, parent)
+ self.session = session
+ self.activeIcon = (view.activeIcon if view else QIcon())
+ self.inactiveIcon = (view.inactiveIcon if view else QIcon())
+ self.setHorizontalHeaderLabels(self.labels)
+
+ def appendRowFromData(self, **kwds):
+ """ Create and append row based on model data and method
parameters.
+
+ """
+ items = self.makeRowItems(**kwds)
+ self.appendRow(items)
+
+ def rowToDict(self, row):
+ """
+
+ """
+ return {
+ 'active':self.item(row, 0).checkState(),
+ 'filename':str(self.item(row, 2).text()),
+ }
+
+ def encodeRows(self):
+ """ Encode model items as dictionaries.
+
+ """
+ return [self.rowToDict(i) for i in range(self.rowCount())]
+
+ def decodeRows(self, rows):
+ """ Yields a list of items for each row.
+
+ """
+ for row in rows:
+ yield self.makeRowItems(icon=self.inactiveIcon,
+ filename=row['filename'])
+
+ def makeRowItems(self, **kwds):
+ """
+
+ """
+ return [
+ StandardItem(checkable=True, checkState=Qt.Unchecked,
+ enabled=True, alignment=Qt.AlignCenter),
+ StandardItem('inactive', icon=kwds.get('icon', QIcon())),
+ StandardItem(kwds.get('filename', '')),
+ ]
+
+
Modified: trunk/profit/workbench/widgets/ui_executionsdisplay.ui
==============================================================================
--- trunk/profit/workbench/widgets/ui_executionsdisplay.ui (original)
+++ trunk/profit/workbench/widgets/ui_executionsdisplay.ui Tue Aug 5
23:24:40 2008
@@ -23,26 +23,7 @@
<widget class="FilterBar" native="1" name="filterBar" />
</item>
<item>
- <widget class="QTableView" name="executionsTable" >
- <property name="frameShape" >
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="frameShadow" >
- <enum>QFrame::Plain</enum>
- </property>
- <property name="alternatingRowColors" >
- <bool>true</bool>
- </property>
- <property name="selectionMode" >
- <enum>QAbstractItemView::SingleSelection</enum>
- </property>
- <property name="selectionBehavior" >
- <enum>QAbstractItemView::SelectRows</enum>
- </property>
- <property name="gridStyle" >
- <enum>Qt::DotLine</enum>
- </property>
- </widget>
+ <widget class="QTreeView" name="executionsView" />
</item>
</layout>
</widget>
Modified: trunk/profit/workbench/widgets/ui_strategydisplay.ui
==============================================================================
--- trunk/profit/workbench/widgets/ui_strategydisplay.ui (original)
+++ trunk/profit/workbench/widgets/ui_strategydisplay.ui Tue Aug 5
23:24:40 2008
@@ -114,29 +114,11 @@
</property>
<layout class="QVBoxLayout" >
<item>
- <widget class="QTableView" name="strategyTable" >
+ <widget class="QTreeView" name="strategyView" >
<property name="frameShape" >
<enum>QFrame::NoFrame</enum>
</property>
- <property name="frameShadow" >
- <enum>QFrame::Plain</enum>
- </property>
- <property name="alternatingRowColors" >
- <bool>true</bool>
- </property>
- <property name="selectionMode" >
- <enum>QAbstractItemView::SingleSelection</enum>
- </property>
- <property name="selectionBehavior" >
- <enum>QAbstractItemView::SelectRows</enum>
- </property>
- <property name="gridStyle" >
- <enum>Qt::DotLine</enum>
- </property>
- <property name="wordWrap" >
- <bool>false</bool>
- </property>
- <property name="cornerButtonEnabled" >
+ <property name="rootIsDecorated" >
<bool>false</bool>
</property>
</widget>
@@ -228,7 +210,6 @@
</layout>
</widget>
<tabstops>
- <tabstop>strategyTable</tabstop>
<tabstop>editButton</tabstop>
<tabstop>removeButton</tabstop>
<tabstop>loadButton</tabstop>
Modified: trunk/profit/workbench/widgets/ui_tickerdisplay.ui
==============================================================================
--- trunk/profit/workbench/widgets/ui_tickerdisplay.ui (original)
+++ trunk/profit/workbench/widgets/ui_tickerdisplay.ui Tue Aug 5 23:24:40
2008
@@ -14,7 +14,29 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" >
<item>
+ <widget class="InfoBar" name="frame_2" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Minimum" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QFrame" name="frame" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
<property name="frameShape" >
<enum>QFrame::StyledPanel</enum>
</property>
@@ -91,6 +113,12 @@
<class>FilterBar</class>
<extends>QWidget</extends>
<header location="global" >profit.lib.widgets.filterbar.h</header>
+ </customwidget>
+ <customwidget>
+ <class>InfoBar</class>
+ <extends>QFrame</extends>
+ <header location="global" >profit.lib.widgets.infobar.h</header>
+ <container>1</container>
</customwidget>
</customwidgets>
<resources/>