Update various UI aspects

Minor menu/UI tweaks, with the addition of some shortcuts.
Reconnecting in the middle of typing shouldn't kill the whole client
now.
It still needs to account for the "reconnecting" window (this will
likely be made to loop back into the query window for now).
This commit is contained in:
karxi 2017-01-09 01:18:59 -05:00
parent c7755899a3
commit c1d03887b4
6 changed files with 124 additions and 52 deletions

View file

@ -59,8 +59,6 @@
* Save commonly-used times on a per-handle basis!
* Make the memo list highlight/recolor the names of channels you're in
(including secret ones)
* Make right-clicking on a tab open up the right-click menu one would get on
right-clicking the title (frame??)
* Add an option to Cycle (for log separation)
* Add a separate 'Tweaks' section in Options
@ -80,15 +78,10 @@
* Enable/Disable toggle (Firefox style option sheet-esque? Seems okay.)
* Ctrl+W closes tab
* Ctrl+Shift+PGUP/PGDN moves tab
* Make Ctrl+J/K usable for tab changing
* Option to disable Ctrl+Tab's jump to newest
* Ctrl+Shift+V "Mass Paste" option (parse lines in sequence)?
* Make system messages use timestamps like everything else
* Offer option for timestamps in memos
* Make certain dialogues start on the safer of the two options
* Make the Reconnect dialog start on reconnect
* Make the Rejoin dialog start on rejoin
* Make the Invite dialog start on decline
* Make a status window/popup to contain logs of information like invites
### "Security"
@ -98,7 +91,7 @@ design.**
If you want Pesterchum to be more secure, either get ghostDunk to make changes
to the server and its administration policies, or get everyone to switch to this
version of the client. There aren't really any other choices.
version of the client. There aren't really any other options.
* Flood protection (don't send because of the same target too many times in a
row)
@ -144,13 +137,23 @@ version of the client. There aren't really any other choices.
## Todo/Done
**Everything in this section has already been completed.**
### GUI
* Toggle individual tab flash / alert sounds (from the same right-click memo
that lets us toggle OOC)
* Make CTRL+PGUP/PGDN switch memo/pester tabs
* Make Ctrl+J/K usable for tab changing
* Make right-clicking on a tab open up the right-click menu one would get on
right-clicking the title (frame??)
* Right-click in userlist offers option to Pester
* Make certain dialogues start on the safer of the two options
* Make the Reconnect dialog start on Reconnect
* Make the Rejoin dialog start on Rejoin
* Make the Invite dialog start on Decline
### Usability
* Fix parser text-loss bug that plagues everyone (especially Chumdroid users)
* Make /me messages that cut continue into more /me messages
* Make sound work on Windows through QSound (disables volume control)
* Toggle individual tab flash / alert sounds (from the same right-click memo
that lets us toggle OOC)
* Make CTRL+PGUP/PGDN switch memo/pester tabs
* Color tags are now posted as their shorter hexadecimal forms, if applicable
(255,255,255 -> #FFFFFF, for example)
* Separate auto-idle and checkbox idle so they don't share a state (and make

View file

@ -9,6 +9,7 @@ import dataobjs, generic, memos, parsetools, ostools
from version import _pcVersion
from pnc.dep.attrdict import AttrDict
#~from styling import styler
_datadir = ostools.getDataDir()
@ -19,6 +20,7 @@ logging.basicConfig(level=logging.WARNING)
class ConsoleWindow(QtGui.QDialog):
#~class ConsoleWindow(styler.PesterBaseWindow):
# A simple console class, cobbled together from the corpse of another.
# This is a holder for our text inputs.
@ -110,6 +112,10 @@ class ConsoleWindow(QtGui.QDialog):
parent.console.is_open = False
parent.console.window = None
def hideEvent(self, event):
parent = self.parent()
parent.console.is_open = False
# Actual console stuff.
def execInConsole(self, scriptstr, env=None):
# Since that's what imports *us*, this should be okay

View file

@ -15,10 +15,11 @@ from parsetools import convertTags, lexMessage, splitMessage, mecmd, colorBegin,
import parsetools
import pnc.lexercon as lexercon
from pnc.dep.attrdict import AttrDict
class PesterTabWindow(QtGui.QFrame):
def __init__(self, mainwindow, parent=None, convo="convo"):
QtGui.QFrame.__init__(self, parent)
super(PesterTabWindow, self).__init__(parent)
self.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
self.setFocusPolicy(QtCore.Qt.ClickFocus)
self.mainwindow = mainwindow
@ -33,6 +34,30 @@ class PesterTabWindow(QtGui.QFrame):
self.connect(self.tabs, QtCore.SIGNAL('tabMoved(int, int)'),
self, QtCore.SLOT('tabMoved(int, int)'))
self.shortcuts = AttrDict()
self.shortcuts.tabNext = QtGui.QShortcut(
QtGui.QKeySequence('Ctrl+j'), self,
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.shortcuts.tabLast = QtGui.QShortcut(
QtGui.QKeySequence('Ctrl+k'), self,
context=QtCore.Qt.WidgetWithChildrenShortcut)
# Note that we use reversed keys here.
self.shortcuts.tabUp = QtGui.QShortcut(
QtGui.QKeySequence('Ctrl+PgDown'), self,
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.shortcuts.tabDn = QtGui.QShortcut(
QtGui.QKeySequence('Ctrl+PgUp'), self,
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.connect(self.shortcuts.tabNext, QtCore.SIGNAL('activated()'),
self, QtCore.SLOT('nudgeTabNext()'))
self.connect(self.shortcuts.tabUp, QtCore.SIGNAL('activated()'),
self, QtCore.SLOT('nudgeTabNext()'))
self.connect(self.shortcuts.tabLast, QtCore.SIGNAL('activated()'),
self, QtCore.SLOT('nudgeTabLast()'))
self.connect(self.shortcuts.tabDn, QtCore.SIGNAL('activated()'),
self, QtCore.SLOT('nudgeTabLast()'))
self.initTheme(self.mainwindow.theme)
self.layout = QtGui.QVBoxLayout()
self.layout.setContentsMargins(0,0,0,0)
@ -96,38 +121,39 @@ class PesterTabWindow(QtGui.QFrame):
nexti = (self.tabIndices[self.currentConvo.title()] + 1) % self.tabs.count()
self.tabs.setCurrentIndex(nexti)
elif (mods == QtCore.Qt.ControlModifier and
keypress in (QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown)):
# Inverted controls. Might add an option for this if people want
# it.
if keypress == QtCore.Qt.Key_PageDown:
direction = 1
elif keypress == QtCore.Qt.Key_PageUp:
direction = -1
# ...Processing...
tabs = self.tabs
# Pick our new index by sliding up or down the tab range.
# NOTE: This feels like it could error. In fact, it /will/ if
# there are no tabs, but...that shouldn't happen, should it?
# There are probably other scenarios, too, so we'll have to
# check on this later.
#
# Calculate the new index.
ct = tabs.count()
cind = tabs.currentIndex()
nind = cind + direction
if nind > (ct - 1):
# The new index would be higher than the maximum; loop.
nind = nind % ct
# Otherwise, negative syntax should get it for us.
nind = range(ct)[nind]
# Change to the selected tab.
# Note that this will send out the usual callbacks that handle
# focusing and such.
tabs.setCurrentIndex(nind)
# Ensure this doesn't fall through normally.
# (Not an issue here, but this used to be on a TextArea.)
return
@QtCore.pyqtSlot()
def nudgeTabNext(self): return self.nudgeTabIndex(+1)
@QtCore.pyqtSlot()
def nudgeTabLast(self): return self.nudgeTabIndex(-1)
def nudgeTabIndex(self, direction):
# Inverted controls. Might add an option for this if people want
# it.
#~if keypress == QtCore.Qt.Key_PageDown:
#~ direction = 1
#~elif keypress == QtCore.Qt.Key_PageUp:
#~ direction = -1
# ...Processing...
tabs = self.tabs
# Pick our new index by sliding up or down the tab range.
# NOTE: This feels like it could error. In fact, it /will/ if
# there are no tabs, but...that shouldn't happen, should it?
# There are probably other scenarios, too, so we'll have to
# check on this later.
#
# Calculate the new index.
ct = tabs.count()
cind = tabs.currentIndex()
nind = cind + direction
if nind > (ct - 1):
# The new index would be higher than the maximum; loop.
nind = nind % ct
# Otherwise, negative syntax should get it for us.
nind = range(ct)[nind]
# Change to the selected tab.
# Note that this will send out the usual callbacks that handle
# focusing and such.
tabs.setCurrentIndex(nind)
def contextMenuEvent(self, event):
#~if event.reason() == QtGui.QContextMenuEvent.Mouse:
@ -450,8 +476,7 @@ class PesterText(QtGui.QTextEdit):
def keyPressEvent(self, event):
# First parent is the PesterConvo containing this.
# Second parent is the PesterTabWindow containing *it*.
pass_to_super = (QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown,
QtCore.Qt.Key_Up, QtCore.Qt.Key_Down)
pass_to_super = (QtCore.Qt.Key_Up, QtCore.Qt.Key_Down)
parent = self.parent()
key = event.key()
keymods = event.modifiers()
@ -554,8 +579,6 @@ class PesterInput(QtGui.QLineEdit):
prev = self.parent().history.prev()
if prev is not None:
self.setText(prev)
elif event.key() in [QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown]:
self.parent().textArea.keyPressEvent(event)
self.parent().mainwindow.idler.time = 0
super(PesterInput, self).keyPressEvent(event)

View file

@ -375,6 +375,9 @@ class PesterMemo(PesterConvo):
self.userlist = RightClickList(self)
self.userlist.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding))
self.userlist.optionsMenu = QtGui.QMenu(self)
self.pesterChumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/pester"], self)
self.connect(self.pesterChumAction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('newPesterSlot()'))
self.addchumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self)
self.connect(self.addchumAction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('addChumSlot()'))
@ -390,6 +393,7 @@ class PesterMemo(PesterConvo):
self.quirkDisableAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirkkill"], self)
self.connect(self.quirkDisableAction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('killQuirkUser()'))
self.userlist.optionsMenu.addAction(self.pesterChumAction)
self.userlist.optionsMenu.addAction(self.addchumAction)
# ban & op list added if we are op
@ -1024,6 +1028,12 @@ class PesterMemo(PesterConvo):
msgbox.setText(self.mainwindow.theme["convo/text/kickedmemo"])
msgbox.setInformativeText("press 0k to rec0nnect or cancel to absc0nd")
msgbox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
# Find the OK button and make it default
for b in msgbox.buttons():
if msgbox.buttonRole(b) == QtGui.QMessageBox.AcceptRole:
# We found the 'OK' button, set it as the default
b.setAutoDefault(True)
break
ret = msgbox.exec_()
if ret == QtGui.QMessageBox.Ok:
self.userlist.clear()
@ -1160,6 +1170,15 @@ class PesterMemo(PesterConvo):
elif c.lower() == self.channel.lower() and h == "" and update[0] in ["+","-"]:
self.updateChanModes(update, op)
@QtCore.pyqtSlot()
def newPesterSlot(self):
# We're opening a pester with someone in our user list.
user = self.userlist.currentItem()
if not user:
return
user = unicode(user.text())
self.mainwindow.newConversation(user)
@QtCore.pyqtSlot()
def addChumSlot(self):
if not self.userlist.currentItem():

View file

@ -1730,6 +1730,9 @@ class LoadingScreen(QtGui.QDialog):
self.loadinglabel = QtGui.QLabel("CONN3CT1NG", self)
self.cancel = QtGui.QPushButton("QU1T >:?", self)
self.ok = QtGui.QPushButton("R3CONN3CT >:]", self)
# Help reduce the number of accidental Pesterchum closures... :|
self.cancel.setAutoDefault(False)
self.ok.setAutoDefault(True)
self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('reject()'))
self.connect(self.ok, QtCore.SIGNAL('clicked()'),

View file

@ -1085,6 +1085,7 @@ class PesterWindow(MovingWindow):
self.memos = CaseInsensitiveDict()
self.tabconvo = None
self.tabmemo = None
self.shortcuts = AttrDict()
if "advanced" in options:
self.advanced = options["advanced"]
else: self.advanced = False
@ -1179,6 +1180,16 @@ class PesterWindow(MovingWindow):
self.console.action = QtGui.QAction("Console", self)
self.connect(self.console.action, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('showConsole()'))
self.console.shortcut = QtGui.QShortcut(
QtGui.QKeySequence("Ctrl+`"), self)
# Make sure the shortcut works anywhere.
# karxi: There's something wrong with the inheritance scheme here.
self.console.shortcut.setContext(QtCore.Qt.ApplicationShortcut)
self.connect(self.console.shortcut, QtCore.SIGNAL('activated()'),
self, QtCore.SLOT('showConsole()'))
#~# Use new-style connections
#~self.console.shortcut.activated.connect(self.showConsole)
# Apparently those can crash sometimes...c'est la vie. Can't use 'em.
self.console.is_open = False
filemenu = self.menu.addMenu(self.theme["main/menus/client/_name"])
@ -2002,6 +2013,12 @@ class PesterWindow(MovingWindow):
msgbox.setText("You're invited!")
msgbox.setInformativeText("%s has invited you to the memo: %s\nWould you like to join them?" % (handle, channel))
msgbox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
# Find the Cancel button and make it default
for b in msgbox.buttons():
if msgbox.buttonRole(b) == QtGui.QMessageBox.RejectRole:
# We found the 'Cancel' button, set it as the default
b.setAutoDefault(True)
break
ret = msgbox.exec_()
if ret == QtGui.QMessageBox.Ok:
self.newMemo(unicode(channel), "+0:00")
@ -2299,6 +2316,11 @@ class PesterWindow(MovingWindow):
secret = self.memochooser.secretChannel.isChecked()
invite = self.memochooser.inviteChannel.isChecked()
# Join the ones on the list first
for SelectedMemo in self.memochooser.SelectedMemos():
channel = "#"+unicode(SelectedMemo.target)
self.newMemo(channel, time)
if self.memochooser.newmemoname():
newmemo = self.memochooser.newmemoname()
channel = unicode(newmemo).replace(" ", "_")
@ -2313,10 +2335,6 @@ class PesterWindow(MovingWindow):
# the server has confirmed that we've joined....
self.newMemo(c, time, secret=secret, invite=invite)
for SelectedMemo in self.memochooser.SelectedMemos():
channel = "#"+unicode(SelectedMemo.target)
self.newMemo(channel, time)
self.memochooser = None
@QtCore.pyqtSlot()
def memoChooserClose(self):