deck and plugin sharing

This commit is contained in:
Damien Elmes 2009-03-11 05:19:02 +09:00
parent 804413604c
commit 2646a40edb
9 changed files with 671 additions and 119 deletions

View file

@ -26,6 +26,7 @@ def importAll():
import update
import utils
import view
import getshared
class DialogManager(object):

View file

@ -4,10 +4,20 @@
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import anki, ankiqt
from anki.exporting import exporters
from anki.exporting import exporters as exporters_
from anki.utils import parseTags
from ankiqt import ui
class PackagedAnkiExporter(object):
def __init__(self, *args):
pass
def exporters():
l = list(exporters_())
l.insert(1, (_("Packaged Anki Deck (*.zip)"),
PackagedAnkiExporter))
return l
class ExportDialog(QDialog):
def __init__(self, parent):
@ -35,7 +45,7 @@ class ExportDialog(QDialog):
self.setTabOrder(self.tags,
self.dialog.includeScheduling)
# save button
b = QPushButton(_("Export to..."))
b = QPushButton(_("Export..."))
self.dialog.buttonBox.addButton(b, QDialogButtonBox.AcceptRole)
def exporterChanged(self, idx):
@ -50,6 +60,9 @@ class ExportDialog(QDialog):
self.dialog.includeTags.hide()
def accept(self):
if isinstance(self.exporter, PackagedAnkiExporter):
self.parent.onShare(parseTags(unicode(self.tags.text())))
return QDialog.accept(self)
file = ui.utils.getSaveFile(self, _("Choose file to export to"), "export",
self.exporter.key, self.exporter.ext)
self.hide()

210
ankiqt/ui/getshared.py Normal file
View file

@ -0,0 +1,210 @@
# -*- coding: utf-8 -*-
# Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtNetwork import *
import ankiqt, simplejson, time, cStringIO, zipfile, tempfile, os, re
from ankiqt.ui.utils import saveGeom, restoreGeom, showInfo
from anki.utils import fmtTimeSpan
R_ID = 0
R_USERNAME = 1
R_TITLE = 2
R_DESCRIPTION = 3
R_TAGS = 4
R_VERSION = 5
R_FACTS = 6
R_SIZE = 7
R_COUNT = 8
R_MODIFIED = 9
R_FNAME = 10
class GetShared(QDialog):
def __init__(self, parent, type):
QDialog.__init__(self, parent, Qt.Window)
self.parent = parent
self.form = ankiqt.forms.getshared.Ui_Dialog()
self.form.setupUi(self)
restoreGeom(self, "getshared")
self.setupTable()
self.onChangeType(type)
self.ok = False
if type == 0:
self.setWindowTitle(_("Download Shared Deck"))
else:
self.setWindowTitle(_("Download Shared Plugin"))
self.exec_()
def setupTable(self):
self.connect(
self.form.table, SIGNAL("currentCellChanged(int,int,int,int)"),
self.onCellChanged)
self.form.table.verticalHeader().setDefaultSectionSize(
self.parent.config['editLineSize'])
self.form.search.setText("search not yet implemented")
def fetchData(self):
h = QHttp(self)
h.connect(h, SIGNAL("requestFinished(int,bool)"), self.onReqFin)
h.setHost("anki.ichi2.net")
#h.setHost("localhost", 8001)
self.conId = h.get("/file/search?t=%d" % self.type)
self.http = h
self.parent.setProgressParent(self)
self.parent.startProgress()
def onReqFin(self, id, err):
"List fetched."
if id != self.conId:
return
self.parent.finishProgress()
self.parent.setProgressParent(None)
if err:
showInfo(_("Unable to connect to server."), parent=self)
self.close()
return
data = self.http.readAll()
self.allList = simplejson.loads(unicode(data))
self.typeChanged()
self.limit()
def limit(self):
self.curList = self.allList
self.redraw()
def redraw(self):
self.form.table.setSortingEnabled(False)
self.form.table.setRowCount(len(self.curList))
self.items = {}
if self.type == 0:
cols = (R_TITLE, R_FACTS, R_MODIFIED)
else:
cols = (R_TITLE, R_MODIFIED)
for rc, r in enumerate(self.curList):
for cc, c in enumerate(cols):
if c == R_MODIFIED:
txt = time.strftime("%m/%Y", time.localtime(r[c]))
else:
txt = unicode(r[c])
item = QTableWidgetItem(txt)
self.items[item] = r
self.form.table.setItem(rc, cc, item)
self.form.table.setSortingEnabled(True)
self.form.table.selectRow(0)
def onCellChanged(self, row, col, x, y):
ci = self.form.table.currentItem()
if not ci:
self.form.bottomLabel.setText(_("Nothing selected."))
return
r = self.items[ci]
self.curRow = r
self.form.bottomLabel.setText(_("""\
<b>Title</b>: %(title)s<br>
<b>Tags</b>: %(tags)s<br>
<b>Size</b>: %(size)0.2fKB<br>
<b>Uploader</b>: %(author)s<br>
<b>Downloads</b>: %(count)s<br>
<b>Description</b>:<br>%(description)s""") % {
'title': r[R_TITLE],
'tags': r[R_TAGS],
'size': r[R_SIZE] / 1024.0,
'author': r[R_USERNAME],
'count': r[R_COUNT],
'description': r[R_DESCRIPTION].replace("\n", "<br>"),
})
self.form.scrollAreaWidgetContents.adjustSize()
self.form.scrollArea.setWidget(self.form.scrollAreaWidgetContents)
def onChangeType(self, type):
self.type = type
self.fetchData()
def typeChanged(self):
self.form.table.clear()
if self.type == 0:
self.form.table.setColumnCount(3)
self.form.table.setHorizontalHeaderLabels([
_("Title"), _("Facts"), _("Modified")])
else:
self.form.table.setColumnCount(2)
self.form.table.setHorizontalHeaderLabels([
_("Title"), _("Modified")])
self.form.table.horizontalHeader().setResizeMode(
0, QHeaderView.Stretch)
self.form.table.verticalHeader().hide()
self.form.table.setSelectionBehavior(QAbstractItemView.SelectRows)
def accept(self):
h = QHttp(self)
h.connect(h, SIGNAL("requestFinished(int,bool)"), self.onReqFin2)
h.setHost("anki.ichi2.net")
#h.setHost("localhost", 8001)
self.conId = h.get("/file/get?id=%d" % self.curRow[R_ID])
self.http = h
self.parent.setProgressParent(self)
self.parent.startProgress()
def onReqFin2(self, id, err):
"File fetched."
if id != self.conId:
return
try:
self.parent.finishProgress()
self.parent.setProgressParent(None)
if err:
showInfo(_("Unable to connect to server."), parent=self)
self.close()
return
data = self.http.readAll()
ext = os.path.splitext(self.curRow[R_FNAME])[1]
if ext == ".zip":
f = cStringIO.StringIO()
f.write(data)
z = zipfile.ZipFile(f)
else:
z = None
tit = self.curRow[R_TITLE]
tit = re.sub("[^][A-Za-z0-9 ()\-]", "", tit)
tit = tit[0:40]
if self.type == 0:
# deck
dd = self.parent.documentDir
p = os.path.join(dd, tit + ".anki")
if os.path.exists(p):
tit += "%d" % time.time()
for l in z.namelist():
if l == "shared.anki":
dpath = os.path.join(dd, tit + ".anki")
open(dpath, "w").write(z.read(l))
elif l.startswith("shared.media/"):
try:
os.mkdir(os.path.join(dd, tit + ".media"))
except OSError:
pass
open(os.path.join(dd, tit + ".media",
os.path.basename(l)),"w").write(z.read(l))
self.parent.loadDeck(dpath)
self.ok = True
else:
pd = self.parent.pluginsFolder()
if z:
raise "nyi"
# for l in z.namelist():
# try:
# os.mkdir(os.path.join(pd, os.path.dirname(l)))
# except OSError:
# pass
# open(os.path.join(pd, 2))
else:
open(os.path.join(pd, tit + ext), "w").write(data)
showInfo(_("Plugin downloaded. Please restart Anki."),
parent=self)
self.ok = True
return
finally:
QDialog.accept(self)

View file

@ -6,8 +6,8 @@ from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtWebKit import QWebPage
import os, sys, re, types, gettext, stat, traceback
import shutil, time, glob, tempfile, datetime
import os, sys, re, types, gettext, stat, traceback, inspect
import shutil, time, glob, tempfile, datetime, zipfile
from PyQt4.QtCore import *
from PyQt4.QtGui import *
@ -627,50 +627,10 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
latest = self.config['recentDeckPaths'][0]
defaultDir = os.path.dirname(latest)
else:
if save:
defaultDir = unicode(os.path.expanduser("~/"),
sys.getfilesystemencoding())
else:
samples = self.getSamplesDir()
if samples:
return samples
return defaultDir
def getSamplesDir(self):
path = os.path.join(ankiqt.runningDir, "libanki")
if not os.path.exists(path):
path = os.path.join(
os.path.join(ankiqt.runningDir, ".."), "libanki")
if not os.path.exists(path):
path = ankiqt.runningDir
if sys.platform.startswith("win32"):
path = os.path.split(
os.path.split(ankiqt.runningDir)[0])[0]
elif sys.platform.startswith("darwin"):
path = ankiqt.runningDir + "/../../.."
path = os.path.join(path, "samples")
path = os.path.normpath(path)
if os.path.exists(path):
if sys.platform.startswith("darwin"):
return self.openMacSamplesDir(path)
return path
return ""
def openMacSamplesDir(self, path):
# some versions of macosx don't allow the open dialog to point inside
# a .App file, it seems - so we copy the files onto the desktop.
newDir = os.path.expanduser("~/Documents/Anki 0.9 Sample Decks")
import shutil
if os.path.exists(newDir):
files = os.listdir(path)
for file in files:
loc = os.path.join(path, file)
if not os.path.exists(os.path.join(newDir, file)):
shutil.copy2(loc, newDir)
return newDir
shutil.copytree(path, newDir)
return newDir
def updateRecentFiles(self, path):
"Add the current deck to the list of recent files."
path = os.path.normpath(path)
@ -762,6 +722,7 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
return True
def inMainWindow(self):
return True
return self.app.activeWindow() == self
def onNew(self, initial=False, path=None):
@ -827,23 +788,27 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
self.deck = None
self.moveToState("initial")
def onOpen(self, samples=False):
def onGetSharedDeck(self):
if not self.inMainWindow(): return
if not self.saveAndClose(hideWelcome=True): return
s = ui.getshared.GetShared(self, 0)
if not s.ok:
self.deck = None
self.moveToState("initial")
def onGetSharedPlugin(self):
if not self.inMainWindow(): return
ui.getshared.GetShared(self, 1)
def onOpen(self):
if not self.inMainWindow(): return
key = _("Deck files (*.anki)")
if samples: defaultDir = self.getSamplesDir()
else: defaultDir = self.getDefaultDir()
defaultDir = self.getDefaultDir()
file = QFileDialog.getOpenFileName(self, _("Open deck"),
defaultDir, key)
file = unicode(file)
if not file:
return False
if samples:
# we need to copy into a writeable location
d = unicode(
os.path.join(self.documentDir, os.path.basename(file)))
if not os.path.exists(d):
shutil.copy(file, d)
file = d
ret = self.loadDeck(file, interactive=True)
if not ret:
if ret is None:
@ -854,9 +819,6 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
self.updateRecentFiles(file)
return True
def onOpenSamples(self):
self.onOpen(samples=True)
def onUnsavedTimer(self):
QToolTip.showText(
self.mainWin.statusbar.mapToGlobal(QPoint(0, -100)),
@ -952,14 +914,12 @@ your deck."""))
def onWelcomeAnchor(self, str):
if str == "new":
self.onNew()
elif str == "sample":
self.onOpenSamples()
elif str == "open":
self.onOpen()
elif str == "sample":
self.onGetSharedDeck()
elif str == "openrem":
self.onOpenOnline()
elif str == "more":
self.onGetMoreDecks()
if str == "addfacts":
if not self.deck:
self.onNew()
@ -1177,7 +1137,6 @@ day = :d""", d=yesterday)
self.deck.newCardSpacing = self.mainWin.newCardScheduling.currentIndex()
self.deck.revCardOrder = self.mainWin.revCardOrder.currentIndex()
self.deck.setFailedCardPolicy(self.mainWin.failedCardsOption.currentIndex())
self.deck.updateDynamicIndices()
self.deck.startSession()
self.deck.flushMod()
self.moveToState("getQuestion")
@ -1403,9 +1362,6 @@ day = :d""", d=yesterday)
def onActiveTags(self):
ui.activetags.show(self)
def onGetMoreDecks(self):
QDesktopServices.openUrl(QUrl(ankiqt.appMoreDecks))
# Importing & exporting
##########################################################################
@ -1417,9 +1373,20 @@ day = :d""", d=yesterday)
def onExport(self):
ui.exporting.ExportDialog(self)
# Cramming
# Cramming & Sharing
##########################################################################
def _copyToTmpDeck(self, name="cram.anki", tags=""):
ndir = tempfile.mkdtemp(prefix="anki")
path = os.path.join(ndir, name)
from anki.exporting import AnkiExporter
e = AnkiExporter(self.deck)
if tags:
e.limitTags = parseTags(tags)
path = unicode(path, sys.getfilesystemencoding())
e.exportInto(path)
return (e, path)
def onCram(self):
if self.deck.name() == "cram":
ui.utils.showInfo(
@ -1433,14 +1400,7 @@ day = :d""", d=yesterday)
return
s = unicode(s)
# open tmp deck
ndir = tempfile.mkdtemp(prefix="anki")
path = os.path.join(ndir, "cram.anki")
from anki.exporting import AnkiExporter
e = AnkiExporter(self.deck)
if s:
e.limitTags = parseTags(s)
path = unicode(path, sys.getfilesystemencoding())
e.exportInto(path)
(e, path) = self._copyToTmpDeck(tags=s)
if not e.exportedCards:
ui.utils.showInfo(_("No cards matched the provided tags."))
return
@ -1484,6 +1444,79 @@ day = :d""", d=yesterday)
self.reset()
p.finish()
def onShare(self, tags):
pwd = os.getcwd()
# open tmp deck
(e, path) = self._copyToTmpDeck(name="shared.anki", tags=tags)
if not e.exportedCards:
ui.utils.showInfo(_("No cards matched the provided tags."))
return
self.deck.startProgress()
self.deck.updateProgress()
d = DeckStorage.Deck(path)
# reset scheduling to defaults
d.newCardsPerDay = 20
d.delay0 = 600
d.delay1 = 600
d.delay2 = 0
d.hardIntervalMin = 0.333
d.hardIntervalMax = 0.5
d.midIntervalMin = 3.0
d.midIntervalMax = 5.0
d.easyIntervalMin = 7.0
d.easyIntervalMax = 9.0
d.syncName = None
d.suspended = u"Suspended"
self.deck.updateProgress()
d.updateAllPriorities()
d.utcOffset = 24
d.flushMod()
d.save()
self.deck.updateProgress()
# remove indices
indices = d.s.column0(
"select name from sqlite_master where type = 'index'")
for i in indices:
d.s.statement("drop index %s" % i)
# and q/a cache
d.s.statement("update cards set question = '', answer = ''")
self.deck.updateProgress()
d.s.statement("vacuum")
self.deck.updateProgress()
nfacts = d.factCount
mdir = d.mediaDir()
d.close()
dir = os.path.dirname(path)
zippath = os.path.join(dir, "shared-%d.zip" % time.time())
# zip it up
zip = zipfile.ZipFile(zippath, "w", zipfile.ZIP_DEFLATED)
zip.writestr("facts", str(nfacts))
readmep = os.path.join(dir, "README.html")
readme = open(readmep, "w")
readme.write('''\
<html><body>
This is an exported packaged deck created by Anki.<p>
To share this deck with other people, upload it to
<a href="http://anki.ichi2.net/file/upload">
http://anki.ichi2.net/file/upload</a>, or email
it to your friends.
</body></html>''')
readme.close()
zip.write(readmep, "README.txt")
zip.write(path, "shared.anki")
if mdir:
for f in os.listdir(mdir):
zip.write(os.path.join(mdir, f),
str(os.path.join("shared.media/", f)))
shutil.rmtree(mdir)
self.deck.updateProgress()
zip.close()
os.chdir(pwd)
os.unlink(path)
self.deck.finishProgress()
self.onOpenPluginFolder(dir)
# Reviewing and learning ahead
##########################################################################
@ -1700,10 +1733,12 @@ day = :d""", d=yesterday)
s = SIGNAL("triggered()")
self.connect(m.actionNew, s, self.onNew)
self.connect(m.actionOpenOnline, s, self.onOpenOnline)
self.connect(m.actionDownloadSharedDeck, s, self.onGetSharedDeck)
self.connect(m.actionDownloadSharedPlugin, s, self.onGetSharedPlugin)
self.connect(m.actionOpen, s, self.onOpen)
self.connect(m.actionOpenSamples, s, self.onOpenSamples)
self.connect(m.actionSave, s, self.onSave)
self.connect(m.actionSaveAs, s, self.onSaveAs)
self.connect(m.actionShare, s, self.onShare)
self.connect(m.actionClose, s, self.onClose)
self.connect(m.actionExit, s, self, SLOT("close()"))
self.connect(m.actionSyncdeck, s, self.syncDeck)
@ -1744,7 +1779,6 @@ day = :d""", d=yesterday)
self.connect(m.actionDisableAllPlugins, s, self.onDisableAllPlugins)
self.connect(m.actionActiveTags, s, self.onActiveTags)
self.connect(m.actionReleaseNotes, s, self.onReleaseNotes)
self.connect(m.actionGetMoreDecks, s, self.onGetMoreDecks)
self.connect(m.actionCacheLatex, s, self.onCacheLatex)
self.connect(m.actionUncacheLatex, s, self.onUncacheLatex)
self.connect(m.actionStudyOptions, s, self.onStudyOptions)
@ -1912,6 +1946,7 @@ day = :d""", d=yesterday)
sys.path.insert(0, plugdir)
plugins = self.enabledPlugins()
plugins.sort()
self.registeredPlugins = {}
for plugin in plugins:
try:
nopy = plugin.replace(".py", "")
@ -1919,6 +1954,7 @@ day = :d""", d=yesterday)
except:
print "Error in %s" % plugin
traceback.print_exc()
self.checkForUpdatedPlugins()
def rebuildPluginsMenu(self):
if getattr(self, "pluginActions", None) is None:
@ -1950,13 +1986,15 @@ day = :d""", d=yesterday)
return [p for p in os.listdir(self.pluginsFolder())
if p.endswith(".py.off") or p.endswith(".py")]
def onOpenPluginFolder(self):
def onOpenPluginFolder(self, path=None):
if path is None:
path = self.pluginsFolder()
if sys.platform == "win32":
# reuse our process handling code from latex
anki.latex.call(["explorer", self.pluginsFolder().encode(
anki.latex.call(["explorer", path.encode(
sys.getfilesystemencoding())])
else:
QDesktopServices.openUrl(QUrl("file://" + self.pluginsFolder()))
QDesktopServices.openUrl(QUrl("file://" + path))
def onGetPlugins(self):
QDesktopServices.openUrl(QUrl("http://ichi2.net/anki/wiki/Plugins"))
@ -1988,6 +2026,14 @@ day = :d""", d=yesterday)
self.enablePlugin(plugin)
self.rebuildPluginsMenu()
def registerPlugin(self, name, updateId):
src = os.path.basename(inspect.getfile(inspect.currentframe(1)))
self.registeredPlugins[src] = {'name': name,
'id': updateId}
def checkForUpdatedPlugins(self):
pass
# Font localisation
##########################################################################
@ -2019,9 +2065,9 @@ day = :d""", d=yesterday)
##########################################################################
def setupProgressInfo(self):
addHook("startProgress", self.onStartProgress)
addHook("updateProgress", self.onUpdateProgress)
addHook("finishProgress", self.onFinishProgress)
addHook("startProgress", self.startProgress)
addHook("updateProgress", self.updateProgress)
addHook("finishProgress", self.finishProgress)
addHook("dbProgress", self.onDbProgress)
addHook("dbFinished", self.onDbFinished)
self.progressParent = None
@ -2032,7 +2078,7 @@ day = :d""", d=yesterday)
def setProgressParent(self, parent):
self.progressParent = parent
def onStartProgress(self, max=100, min=0, title=None):
def startProgress(self, max=0, min=0, title=None):
if self.mainThread != QThread.currentThread():
return
self.setBusy()
@ -2042,14 +2088,14 @@ day = :d""", d=yesterday)
p = ui.utils.ProgressWin(parent, max, min, title)
self.progressWins.append(p)
def onUpdateProgress(self, label=None, value=None):
def updateProgress(self, label=None, value=None):
if self.mainThread != QThread.currentThread():
return
if self.progressWins:
self.progressWins[-1].update(label, value)
self.app.processEvents()
def onFinishProgress(self):
def finishProgress(self):
if self.mainThread != QThread.currentThread():
return
if self.progressWins:

View file

@ -272,25 +272,18 @@ Start adding your own material.</td>
<td valign=middle><h2><a href="welcome:open">Open Local Deck</a></h2></td>
</tr>
<tr>
<td>
<a href="welcome:openrem"><img src=":/icons/document-open-remote.png"></a>
</td>
<td valign=middle><h2><a href="welcome:openrem">Open Online Deck</a></h2></td>
</tr>
<tr>
<td width=50>
<a href="welcome:sample"><img src=":/icons/anki.png"></a>
</td>
<td valign=middle><h2><a href="welcome:sample">Open Sample Deck</a></h2></td>
<td valign=middle><h2><a href="welcome:sample">Download Shared Deck</a></h2></td>
</tr>
<tr>
<td width=50>
<a href="welcome:more"><img src=":/icons/khtml_kget.png"></a>
<td>
<a href="welcome:openrem"><img src=":/icons/document-open-remote.png"></a>
</td>
<td valign=middle><h2><a href="welcome:more">Get More Decks</a></h2></td>
<td valign=middle><h2><a href="welcome:openrem">Download Personal Deck</a></h2></td>
</tr>
</table>"""))

View file

@ -58,6 +58,19 @@
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer" >
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >

121
designer/getshared.ui Normal file
View file

@ -0,0 +1,121 @@
<ui version="4.0" >
<class>Dialog</class>
<widget class="QDialog" name="Dialog" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>517</width>
<height>411</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout" >
<item>
<layout class="QHBoxLayout" name="horizontalLayout" >
<item>
<widget class="QLabel" name="searchLabel" >
<property name="text" >
<string>Search:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="search" />
</item>
</layout>
</item>
<item>
<widget class="QSplitter" name="splitter" >
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<widget class="QTableWidget" name="table" />
<widget class="QScrollArea" name="scrollArea" >
<property name="frameShape" >
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow" >
<enum>QFrame::Plain</enum>
</property>
<property name="verticalScrollBarPolicy" >
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy" >
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>494</width>
<height>54</height>
</rect>
</property>
<property name="sizePolicy" >
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" >
<item>
<widget class="QLabel" name="bottomLabel" >
<property name="text" >
<string>Loading...</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel" >
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel" >
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -1174,7 +1174,6 @@
<addaction name="actionReportbug" />
<addaction name="actionForum" />
<addaction name="actionReleaseNotes" />
<addaction name="actionGetMoreDecks" />
<addaction name="separator" />
<addaction name="actionDonate" />
<addaction name="actionAbout" />
@ -1208,10 +1207,23 @@
<normaloff>:/icons/document-open-recent.png</normaloff>:/icons/document-open-recent.png</iconset>
</property>
</widget>
<widget class="QMenu" name="menuDownload" >
<property name="title" >
<string>&amp;Download...</string>
</property>
<property name="icon" >
<iconset resource="../icons.qrc" >
<normaloff>:/icons/document-open-remote.png</normaloff>:/icons/document-open-remote.png</iconset>
</property>
<addaction name="actionOpenOnline" />
<addaction name="separator" />
<addaction name="actionDownloadSharedDeck" />
<addaction name="actionDownloadSharedPlugin" />
</widget>
<addaction name="actionNew" />
<addaction name="actionOpen" />
<addaction name="menuOpenRecent" />
<addaction name="actionOpenOnline" />
<addaction name="menuDownload" />
<addaction name="actionImport" />
<addaction name="separator" />
<addaction name="actionSave" />
@ -1288,7 +1300,6 @@
<addaction name="actionDisableAllPlugins" />
<addaction name="separator" />
</widget>
<addaction name="actionGetPlugins" />
<addaction name="actionOpenPluginFolder" />
<addaction name="separator" />
<addaction name="menuStartup" />
@ -1762,15 +1773,6 @@
<string>Check Media Database...</string>
</property>
</action>
<action name="actionOpenOnline" >
<property name="icon" >
<iconset resource="../icons.qrc" >
<normaloff>:/icons/document-open-remote.png</normaloff>:/icons/document-open-remote.png</iconset>
</property>
<property name="text" >
<string>Open On&amp;line...</string>
</property>
</action>
<action name="actionCram" >
<property name="icon" >
<iconset resource="../icons.qrc" >
@ -1823,15 +1825,6 @@
<string>Active &amp;Tags...</string>
</property>
</action>
<action name="actionGetMoreDecks" >
<property name="icon" >
<iconset resource="../icons.qrc" >
<normaloff>:/icons/download.png</normaloff>:/icons/download.png</iconset>
</property>
<property name="text" >
<string>&amp;Get More Decks...</string>
</property>
</action>
<action name="actionEditCurrent" >
<property name="icon" >
<iconset resource="../icons.qrc" >
@ -1904,6 +1897,34 @@
<string>&amp;Record Noise Profile...</string>
</property>
</action>
<action name="actionGetShared" >
<property name="text" >
<string>Get Shared...</string>
</property>
<property name="statusTip" >
<string>Open a pre-made deck or plugin</string>
</property>
</action>
<action name="actionShare" >
<property name="text" >
<string>Share...</string>
</property>
</action>
<action name="actionOpenOnline" >
<property name="text" >
<string>Personal Deck</string>
</property>
</action>
<action name="actionDownloadSharedDeck" >
<property name="text" >
<string>Shared Deck</string>
</property>
</action>
<action name="actionDownloadSharedPlugin" >
<property name="text" >
<string>Shared Plugin</string>
</property>
</action>
</widget>
<tabstops>
<tabstop>newPerDay</tabstop>

134
designer/share.ui Normal file
View file

@ -0,0 +1,134 @@
<ui version="4.0" >
<class>Dialog</class>
<widget class="QDialog" name="Dialog" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>517</width>
<height>411</height>
</rect>
</property>
<property name="windowTitle" >
<string>Get Shared Decks/Plugins</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" >
<item>
<layout class="QHBoxLayout" name="horizontalLayout" >
<item>
<widget class="QLabel" name="searchLabel" >
<property name="text" >
<string>Search:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="search" />
</item>
<item>
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>Type:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="type" />
</item>
</layout>
</item>
<item>
<widget class="QSplitter" name="splitter" >
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<widget class="QTableWidget" name="table" />
<widget class="QScrollArea" name="scrollArea" >
<property name="frameShape" >
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow" >
<enum>QFrame::Plain</enum>
</property>
<property name="verticalScrollBarPolicy" >
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy" >
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>494</width>
<height>54</height>
</rect>
</property>
<property name="sizePolicy" >
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" >
<item>
<widget class="QLabel" name="bottomLabel" >
<property name="text" >
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel" >
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel" >
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>