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()
mw = ui.main.AnkiQt(app, conf, args)
try:
styleFile = open(opts.config + ".css")
styleFile = open(os.path.join(opts.config, "style.css"))
mw.setStyleSheet(styleFile.read())
except (IOError, OSError):
pass

View file

@ -62,13 +62,6 @@ class AddCards(QDialog):
QDialogButtonBox.HelpRole)
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):
oldFact = self.editor.fact
# create a new fact

View file

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

View file

@ -4,6 +4,7 @@
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtWebKit import QWebPage
import os, sys, re, types, gettext, stat, traceback
import copy, shutil, time, glob
@ -54,6 +55,9 @@ class AnkiQt(QMainWindow):
self.addView(self.bodyView)
self.statusView = ui.status.StatusView(self)
self.addView(self.statusView)
self.mainWin.welcomeText.hide()
self.mainWin.mainText.hide()
self.setupEditor()
self.setupButtons()
self.setupAnchors()
self.setupToolbar()
@ -110,6 +114,7 @@ class AnkiQt(QMainWindow):
# reset current card and load again
self.currentCard = None
self.lastCard = None
self.editor.deck = self.deck
if self.deck:
self.mainWin.menu_Lookup.setEnabled(True)
self.enableDeckMenuItems()
@ -128,9 +133,11 @@ class AnkiQt(QMainWindow):
self.lastState = getattr(self, "state", None)
self.state = state
self.updateTitleBar()
if 'state' != 'noDeck':
if 'state' != 'noDeck' and state != 'editCurrentFact':
self.mainWin.welcomeText.hide()
self.mainWin.mainText.show()
self.mainWin.buttonWidget.show()
self.mainWin.fieldsArea.hide()
if state == "noDeck":
self.mainWin.welcomeText.show()
self.mainWin.mainText.hide()
@ -183,6 +190,14 @@ class AnkiQt(QMainWindow):
self.resetButtons()
self.showEaseButtons()
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)
def keyPressEvent(self, evt):
@ -751,12 +766,19 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
self.onAddCard()
def setupAnchors(self):
# welcome
self.anchorPrefixes = {
'welcome': self.onWelcomeAnchor,
}
self.connect(self.mainWin.welcomeText,
SIGNAL("anchorClicked(QUrl)"),
self.anchorClicked)
# main
self.mainWin.mainText.page().setLinkDelegationPolicy(
QWebPage.DelegateExternalLinks)
self.connect(self.mainWin.mainText,
SIGNAL("linkClicked(QUrl)"),
self.linkClicked)
def anchorClicked(self, url):
# prevent the link being handled
@ -769,6 +791,36 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
# open in browser
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
##########################################################################
@ -783,6 +835,7 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
mw.toolBar.hide()
mw.toolBar = QToolBar(self)
mw.toolBar.addAction(mw.actionAddcards)
mw.toolBar.addAction(mw.actionEditCurrent)
mw.toolBar.addAction(mw.actionEditdeck)
mw.toolBar.addAction(mw.actionRepeatAudio)
mw.toolBar.addAction(mw.actionMarkCard)
@ -932,6 +985,9 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
def onEditDeck(self):
ui.dialogs.get("CardList", self)
def onEditCurrent(self):
self.moveToState("editCurrentFact")
def onDeckProperties(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.actionAddcards, s, self.onAddCard)
self.connect(m.actionEditdeck, s, self.onEditDeck)
self.connect(m.actionEditCurrent, s, self.onEditCurrent)
self.connect(m.actionPreferences, s, self.onPrefs)
self.connect(m.actionLookup_es, s, self.onLookupEdictSelection)
self.connect(m.actionLookup_esk, s, self.onLookupEdictKanjiSelection)

View file

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

View file

@ -5,8 +5,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>505</width>
<height>367</height>
<width>509</width>
<height>381</height>
</rect>
</property>
<property name="windowTitle" >
@ -21,15 +21,25 @@
</property>
<item>
<layout class="QGridLayout" >
<property name="margin" >
<property name="horizontalSpacing" >
<number>0</number>
</property>
<property name="spacing" >
<property name="verticalSpacing" >
<number>4</number>
</property>
<property name="margin" >
<number>0</number>
</property>
<item row="0" column="0" >
<widget class="QWidget" native="1" name="modelArea" />
</item>
<item row="1" column="0" >
<widget class="Line" name="line" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
@ -41,53 +51,48 @@
<property name="sizePolicy" >
<sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
<horstretch>0</horstretch>
<verstretch>5</verstretch>
<verstretch>10</verstretch>
</sizepolicy>
</property>
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="title" >
<string>Fields</string>
<string/>
</property>
<property name="flat" >
<bool>true</bool>
</property>
</widget>
<widget class="QGroupBox" name="statusGroup" >
<widget class="QTextEdit" name="status" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="sizePolicy" >
<sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="title" >
<string>Status</string>
<property name="autoFillBackground" >
<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>
<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>
</item>

View file

@ -5,8 +5,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>532</width>
<height>442</height>
<width>454</width>
<height>504</height>
</rect>
</property>
<property name="sizePolicy" >
@ -27,8 +27,8 @@
<rect>
<x>0</x>
<y>69</y>
<width>532</width>
<height>353</height>
<width>454</width>
<height>415</height>
</rect>
</property>
<property name="sizePolicy" >
@ -129,6 +129,28 @@
<property name="margin" >
<number>5</number>
</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>
<widget class="QTextBrowser" name="welcomeText" >
<property name="focusPolicy" >
@ -351,7 +373,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>532</width>
<width>454</width>
<height>23</height>
</rect>
</property>
@ -376,6 +398,7 @@
<addaction name="actionUndoAnswer" />
<addaction name="separator" />
<addaction name="actionAddcards" />
<addaction name="actionEditCurrent" />
<addaction name="actionEditdeck" />
<addaction name="separator" />
<addaction name="actionActiveTags" />
@ -487,8 +510,8 @@
<property name="geometry" >
<rect>
<x>0</x>
<y>422</y>
<width>532</width>
<y>484</y>
<width>454</width>
<height>20</height>
</rect>
</property>
@ -501,7 +524,7 @@
<rect>
<x>0</x>
<y>23</y>
<width>532</width>
<width>454</width>
<height>46</height>
</rect>
</property>
@ -526,6 +549,7 @@
<addaction name="actionSyncdeck" />
<addaction name="separator" />
<addaction name="actionAddcards" />
<addaction name="actionEditCurrent" />
<addaction name="actionEditdeck" />
<addaction name="actionDisplayProperties" />
<addaction name="separator" />
@ -617,7 +641,7 @@
<string>&amp;Add Items..</string>
</property>
<property name="shortcut" >
<string>Ctrl+A</string>
<string>Alt+Shift+A</string>
</property>
</action>
<action name="actionEditdeck" >
@ -626,10 +650,10 @@
<normaloff>:/icons/view_text.png</normaloff>:/icons/view_text.png</iconset>
</property>
<property name="text" >
<string>&amp;Edit Items..</string>
<string>Ed&amp;it All..</string>
</property>
<property name="shortcut" >
<string>Ctrl+E</string>
<string>Alt+Shift+I</string>
</property>
</action>
<action name="actionPreferences" >
@ -999,6 +1023,18 @@
<string>&amp;Get More Decks..</string>
</property>
</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>
<customwidgets>
<customwidget>

View file

@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/" >
<file>icons/edit-rename.png</file>
<file>icons/kblogger.png</file>
<file>icons/chronometer.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