inline edit, fix images, css, scroll to bottom, status, etc

- new edit card inline mode
- provide file:// url for images for webkit
- look for the css file inside the anki dir
- make add cards dialog more compact
- launch clicked links in external window
This commit is contained in:
Damien Elmes 2008-11-21 20:05:15 +09:00
parent ae776365b1
commit 518fcc3442
9 changed files with 164 additions and 68 deletions

View file

@ -100,7 +100,7 @@ def run():
ui.dialogs.registerDialogs() ui.dialogs.registerDialogs()
mw = ui.main.AnkiQt(app, conf, args) mw = ui.main.AnkiQt(app, conf, args)
try: try:
styleFile = open(opts.config + ".css") styleFile = open(os.path.join(opts.config, "style.css"))
mw.setStyleSheet(styleFile.read()) mw.setStyleSheet(styleFile.read())
except (IOError, OSError): except (IOError, OSError):
pass pass

View file

@ -62,13 +62,6 @@ class AddCards(QDialog):
QDialogButtonBox.HelpRole) QDialogButtonBox.HelpRole)
self.connect(self.helpButton, SIGNAL("clicked()"), self.helpRequested) self.connect(self.helpButton, SIGNAL("clicked()"), self.helpRequested)
def setupStatus(self):
"Make the status background the same colour as the frame."
p = self.dialog.statusGroup.palette()
c = unicode(p.color(QPalette.Window).name())
self.dialog.status.setStyleSheet(
"* { background: %s; color: #000000; }" % c)
def modelChanged(self, model): def modelChanged(self, model):
oldFact = self.editor.fact oldFact = self.editor.fact
# create a new fact # create a new fact

View file

@ -49,7 +49,7 @@ class FactEditor(object):
self.fields = {} self.fields = {}
# top level vbox # top level vbox
self.fieldsBox = QVBoxLayout(self.widget) self.fieldsBox = QVBoxLayout(self.widget)
self.fieldsBox.setMargin(5) self.fieldsBox.setMargin(0)
self.fieldsBox.setSpacing(3) self.fieldsBox.setSpacing(3)
# icons # icons
self.iconsBox = QHBoxLayout() self.iconsBox = QHBoxLayout()
@ -110,7 +110,7 @@ class FactEditor(object):
self.foregroundFrame.setAutoFillBackground(True) self.foregroundFrame.setAutoFillBackground(True)
hbox = QHBoxLayout() hbox = QHBoxLayout()
hbox.addWidget(self.foregroundFrame) hbox.addWidget(self.foregroundFrame)
hbox.setMargin(5) hbox.setMargin(0)
self.foreground.setLayout(hbox) self.foreground.setLayout(hbox)
self.iconsBox.addWidget(self.foreground) self.iconsBox.addWidget(self.foreground)
self.foreground.setStyle(self.plastiqueStyle) self.foreground.setStyle(self.plastiqueStyle)

View file

@ -4,6 +4,7 @@
from PyQt4.QtGui import * from PyQt4.QtGui import *
from PyQt4.QtCore import * from PyQt4.QtCore import *
from PyQt4.QtWebKit import QWebPage
import os, sys, re, types, gettext, stat, traceback import os, sys, re, types, gettext, stat, traceback
import copy, shutil, time, glob import copy, shutil, time, glob
@ -54,6 +55,9 @@ class AnkiQt(QMainWindow):
self.addView(self.bodyView) self.addView(self.bodyView)
self.statusView = ui.status.StatusView(self) self.statusView = ui.status.StatusView(self)
self.addView(self.statusView) self.addView(self.statusView)
self.mainWin.welcomeText.hide()
self.mainWin.mainText.hide()
self.setupEditor()
self.setupButtons() self.setupButtons()
self.setupAnchors() self.setupAnchors()
self.setupToolbar() self.setupToolbar()
@ -110,6 +114,7 @@ class AnkiQt(QMainWindow):
# reset current card and load again # reset current card and load again
self.currentCard = None self.currentCard = None
self.lastCard = None self.lastCard = None
self.editor.deck = self.deck
if self.deck: if self.deck:
self.mainWin.menu_Lookup.setEnabled(True) self.mainWin.menu_Lookup.setEnabled(True)
self.enableDeckMenuItems() self.enableDeckMenuItems()
@ -128,9 +133,11 @@ class AnkiQt(QMainWindow):
self.lastState = getattr(self, "state", None) self.lastState = getattr(self, "state", None)
self.state = state self.state = state
self.updateTitleBar() self.updateTitleBar()
if 'state' != 'noDeck': if 'state' != 'noDeck' and state != 'editCurrentFact':
self.mainWin.welcomeText.hide() self.mainWin.welcomeText.hide()
self.mainWin.mainText.show() self.mainWin.mainText.show()
self.mainWin.buttonWidget.show()
self.mainWin.fieldsArea.hide()
if state == "noDeck": if state == "noDeck":
self.mainWin.welcomeText.show() self.mainWin.welcomeText.show()
self.mainWin.mainText.hide() self.mainWin.mainText.hide()
@ -183,6 +190,14 @@ class AnkiQt(QMainWindow):
self.resetButtons() self.resetButtons()
self.showEaseButtons() self.showEaseButtons()
self.enableCardMenuItems() self.enableCardMenuItems()
elif state == "editCurrentFact":
self.resetButtons()
self.showSaveEditorButton()
self.mainWin.mainText.hide()
self.mainWin.fieldsArea.show()
self.editor.setFact(self.currentCard.fact)
elif state == "saveEdit":
return self.moveToState("auto")
self.updateViews(state) self.updateViews(state)
def keyPressEvent(self, evt): def keyPressEvent(self, evt):
@ -751,12 +766,19 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
self.onAddCard() self.onAddCard()
def setupAnchors(self): def setupAnchors(self):
# welcome
self.anchorPrefixes = { self.anchorPrefixes = {
'welcome': self.onWelcomeAnchor, 'welcome': self.onWelcomeAnchor,
} }
self.connect(self.mainWin.welcomeText, self.connect(self.mainWin.welcomeText,
SIGNAL("anchorClicked(QUrl)"), SIGNAL("anchorClicked(QUrl)"),
self.anchorClicked) self.anchorClicked)
# main
self.mainWin.mainText.page().setLinkDelegationPolicy(
QWebPage.DelegateExternalLinks)
self.connect(self.mainWin.mainText,
SIGNAL("linkClicked(QUrl)"),
self.linkClicked)
def anchorClicked(self, url): def anchorClicked(self, url):
# prevent the link being handled # prevent the link being handled
@ -769,6 +791,36 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
# open in browser # open in browser
QDesktopServices.openUrl(QUrl(url)) QDesktopServices.openUrl(QUrl(url))
def linkClicked(self, url):
QDesktopServices.openUrl(QUrl(url))
# Edit current fact
##########################################################################
def setupEditor(self):
self.mainWin.fieldsArea.hide()
self.editor = ui.facteditor.FactEditor(
self, self.mainWin.fieldsArea, self.deck)
self.editor.onFactValid = self.onFactValid
self.editor.onFactInvalid = self.onFactInvalid
def showSaveEditorButton(self):
if self.lastState == self.state:
return
self.editFactButton = QPushButton(_("Return (Esc)"))
self.editFactButton.setFixedHeight(self.easeButtonHeight)
self.editFactButton.setShortcut(_("Esc"))
self.editFactButton.setDefault(False)
self.buttonBox.addWidget(self.editFactButton)
self.connect(self.editFactButton, SIGNAL("clicked()"),
lambda: self.moveToState("saveEdit"))
def onFactValid(self, fact):
self.editFactButton.setEnabled(True)
def onFactInvalid(self, fact):
self.editFactButton.setEnabled(False)
# Toolbar # Toolbar
########################################################################## ##########################################################################
@ -783,6 +835,7 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
mw.toolBar.hide() mw.toolBar.hide()
mw.toolBar = QToolBar(self) mw.toolBar = QToolBar(self)
mw.toolBar.addAction(mw.actionAddcards) mw.toolBar.addAction(mw.actionAddcards)
mw.toolBar.addAction(mw.actionEditCurrent)
mw.toolBar.addAction(mw.actionEditdeck) mw.toolBar.addAction(mw.actionEditdeck)
mw.toolBar.addAction(mw.actionRepeatAudio) mw.toolBar.addAction(mw.actionRepeatAudio)
mw.toolBar.addAction(mw.actionMarkCard) mw.toolBar.addAction(mw.actionMarkCard)
@ -932,6 +985,9 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
def onEditDeck(self): def onEditDeck(self):
ui.dialogs.get("CardList", self) ui.dialogs.get("CardList", self)
def onEditCurrent(self):
self.moveToState("editCurrentFact")
def onDeckProperties(self): def onDeckProperties(self):
self.deckProperties = ui.deckproperties.DeckProperties(self) self.deckProperties = ui.deckproperties.DeckProperties(self)
@ -1213,6 +1269,7 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
self.connect(m.actionDisplayProperties, s,self.onDisplayProperties) self.connect(m.actionDisplayProperties, s,self.onDisplayProperties)
self.connect(m.actionAddcards, s, self.onAddCard) self.connect(m.actionAddcards, s, self.onAddCard)
self.connect(m.actionEditdeck, s, self.onEditDeck) self.connect(m.actionEditdeck, s, self.onEditDeck)
self.connect(m.actionEditCurrent, s, self.onEditCurrent)
self.connect(m.actionPreferences, s, self.onPrefs) self.connect(m.actionPreferences, s, self.onPrefs)
self.connect(m.actionLookup_es, s, self.onLookupEdictSelection) self.connect(m.actionLookup_es, s, self.onLookupEdictSelection)
self.connect(m.actionLookup_esk, s, self.onLookupEdictKanjiSelection) self.connect(m.actionLookup_esk, s, self.onLookupEdictKanjiSelection)

View file

@ -4,12 +4,11 @@
from PyQt4.QtGui import * from PyQt4.QtGui import *
from PyQt4.QtCore import * from PyQt4.QtCore import *
from PyQt4.QtWebKit import QWebPage
import anki, anki.utils import anki, anki.utils
from anki.sound import playFromText, stripSounds from anki.sound import playFromText, stripSounds
from anki.latex import renderLatex, stripLatex from anki.latex import renderLatex, stripLatex
from anki.utils import stripHTML from anki.utils import stripHTML
import types, time import types, time, re, os
from ankiqt import ui from ankiqt import ui
# Views - define the way a user is prompted for questions, etc # Views - define the way a user is prompted for questions, etc
@ -110,19 +109,24 @@ class View(object):
# Question and answer # Question and answer
########################################################################## ##########################################################################
def munge(self, txt):
txt = renderLatex(self.main.deck, txt)
txt = stripSounds(txt)
txt = re.sub(
'img src="(.*?)"', 'img src="file://%s/\\1"' % os.getcwd(), txt)
return txt
def drawQuestion(self, nosound=False): def drawQuestion(self, nosound=False):
"Show the question." "Show the question."
q = self.main.currentCard.htmlQuestion() q = self.main.currentCard.htmlQuestion()
q = renderLatex(self.main.deck, q) self.write(self.munge(q))
self.write(stripSounds(q))
if self.state != self.oldState and not nosound: if self.state != self.oldState and not nosound:
playFromText(q) playFromText(q)
def drawAnswer(self): def drawAnswer(self):
"Show the answer." "Show the answer."
a = self.main.currentCard.htmlAnswer() a = self.main.currentCard.htmlAnswer()
a = renderLatex(self.main.deck, a) self.write('<span id=answer />' + self.munge(a))
self.write('<span id=answer />' + stripSounds(a))
if self.state != self.oldState: if self.state != self.oldState:
playFromText(a) playFromText(a)

View file

@ -5,8 +5,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>505</width> <width>509</width>
<height>367</height> <height>381</height>
</rect> </rect>
</property> </property>
<property name="windowTitle" > <property name="windowTitle" >
@ -21,15 +21,25 @@
</property> </property>
<item> <item>
<layout class="QGridLayout" > <layout class="QGridLayout" >
<property name="margin" > <property name="horizontalSpacing" >
<number>0</number> <number>0</number>
</property> </property>
<property name="spacing" > <property name="verticalSpacing" >
<number>4</number>
</property>
<property name="margin" >
<number>0</number> <number>0</number>
</property> </property>
<item row="0" column="0" > <item row="0" column="0" >
<widget class="QWidget" native="1" name="modelArea" /> <widget class="QWidget" native="1" name="modelArea" />
</item> </item>
<item row="1" column="0" >
<widget class="Line" name="line" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@ -41,53 +51,48 @@
<property name="sizePolicy" > <property name="sizePolicy" >
<sizepolicy vsizetype="Expanding" hsizetype="Preferred" > <sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>5</verstretch> <verstretch>10</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="title" > <property name="title" >
<string>Fields</string> <string/>
</property>
<property name="flat" >
<bool>true</bool>
</property> </property>
</widget> </widget>
<widget class="QGroupBox" name="statusGroup" > <widget class="QTextEdit" name="status" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="sizePolicy" > <property name="sizePolicy" >
<sizepolicy vsizetype="Preferred" hsizetype="Preferred" > <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>1</verstretch> <verstretch>1</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="title" > <property name="autoFillBackground" >
<string>Status</string> <bool>true</bool>
</property>
<property name="frameShape" >
<enum>QFrame::NoFrame</enum>
</property>
<property name="verticalScrollBarPolicy" >
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy" >
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="html" >
<string>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
p, li { white-space: pre-wrap; }
&lt;/style>&lt;/head>&lt;body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;">
&lt;p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;/p>&lt;/body>&lt;/html></string>
</property> </property>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>0</number>
</property>
<property name="margin" >
<number>0</number>
</property>
<item>
<widget class="QTextEdit" name="status" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="sizePolicy" >
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape" >
<enum>QFrame::NoFrame</enum>
</property>
<property name="verticalScrollBarPolicy" >
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy" >
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</widget> </widget>
</item> </item>

View file

@ -5,8 +5,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>532</width> <width>454</width>
<height>442</height> <height>504</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy" > <property name="sizePolicy" >
@ -27,8 +27,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>69</y> <y>69</y>
<width>532</width> <width>454</width>
<height>353</height> <height>415</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy" > <property name="sizePolicy" >
@ -129,6 +129,28 @@
<property name="margin" > <property name="margin" >
<number>5</number> <number>5</number>
</property> </property>
<item>
<widget class="QGroupBox" name="fieldsArea" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
<horstretch>7</horstretch>
<verstretch>2</verstretch>
</sizepolicy>
</property>
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="title" >
<string/>
</property>
<property name="flat" >
<bool>true</bool>
</property>
<property name="checkable" >
<bool>false</bool>
</property>
</widget>
</item>
<item> <item>
<widget class="QTextBrowser" name="welcomeText" > <widget class="QTextBrowser" name="welcomeText" >
<property name="focusPolicy" > <property name="focusPolicy" >
@ -351,7 +373,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>532</width> <width>454</width>
<height>23</height> <height>23</height>
</rect> </rect>
</property> </property>
@ -376,6 +398,7 @@
<addaction name="actionUndoAnswer" /> <addaction name="actionUndoAnswer" />
<addaction name="separator" /> <addaction name="separator" />
<addaction name="actionAddcards" /> <addaction name="actionAddcards" />
<addaction name="actionEditCurrent" />
<addaction name="actionEditdeck" /> <addaction name="actionEditdeck" />
<addaction name="separator" /> <addaction name="separator" />
<addaction name="actionActiveTags" /> <addaction name="actionActiveTags" />
@ -487,8 +510,8 @@
<property name="geometry" > <property name="geometry" >
<rect> <rect>
<x>0</x> <x>0</x>
<y>422</y> <y>484</y>
<width>532</width> <width>454</width>
<height>20</height> <height>20</height>
</rect> </rect>
</property> </property>
@ -501,7 +524,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>23</y> <y>23</y>
<width>532</width> <width>454</width>
<height>46</height> <height>46</height>
</rect> </rect>
</property> </property>
@ -526,6 +549,7 @@
<addaction name="actionSyncdeck" /> <addaction name="actionSyncdeck" />
<addaction name="separator" /> <addaction name="separator" />
<addaction name="actionAddcards" /> <addaction name="actionAddcards" />
<addaction name="actionEditCurrent" />
<addaction name="actionEditdeck" /> <addaction name="actionEditdeck" />
<addaction name="actionDisplayProperties" /> <addaction name="actionDisplayProperties" />
<addaction name="separator" /> <addaction name="separator" />
@ -617,7 +641,7 @@
<string>&amp;Add Items..</string> <string>&amp;Add Items..</string>
</property> </property>
<property name="shortcut" > <property name="shortcut" >
<string>Ctrl+A</string> <string>Alt+Shift+A</string>
</property> </property>
</action> </action>
<action name="actionEditdeck" > <action name="actionEditdeck" >
@ -626,10 +650,10 @@
<normaloff>:/icons/view_text.png</normaloff>:/icons/view_text.png</iconset> <normaloff>:/icons/view_text.png</normaloff>:/icons/view_text.png</iconset>
</property> </property>
<property name="text" > <property name="text" >
<string>&amp;Edit Items..</string> <string>Ed&amp;it All..</string>
</property> </property>
<property name="shortcut" > <property name="shortcut" >
<string>Ctrl+E</string> <string>Alt+Shift+I</string>
</property> </property>
</action> </action>
<action name="actionPreferences" > <action name="actionPreferences" >
@ -999,6 +1023,18 @@
<string>&amp;Get More Decks..</string> <string>&amp;Get More Decks..</string>
</property> </property>
</action> </action>
<action name="actionEditCurrent" >
<property name="icon" >
<iconset resource="../icons.qrc" >
<normaloff>:/icons/edit-rename.png</normaloff>:/icons/edit-rename.png</iconset>
</property>
<property name="text" >
<string>&amp;Edit Current..</string>
</property>
<property name="shortcut" >
<string>Alt+Shift+E</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View file

@ -1,5 +1,6 @@
<RCC> <RCC>
<qresource prefix="/" > <qresource prefix="/" >
<file>icons/edit-rename.png</file>
<file>icons/kblogger.png</file> <file>icons/kblogger.png</file>
<file>icons/chronometer.png</file> <file>icons/chronometer.png</file>
<file>icons/Anki_Card.png</file> <file>icons/Anki_Card.png</file>

BIN
icons/edit-rename.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 B