Add a curses terminal interface as an alternative to QT #666
|
@ -1,27 +1,54 @@
|
||||||
# Copyright (c) 2014 Luke Montalvo <lukemontalvo@gmail.com>
|
# Copyright (c) 2014 Luke Montalvo <lukemontalvo@gmail.com>
|
||||||
# This file adds a alternative commandline interface
|
# This file adds a alternative commandline interface
|
||||||
|
#
|
||||||
|
# Dependencies:
|
||||||
|
# * from python2-pip
|
||||||
|
# * python2-pythondialog
|
||||||
|
# * dialog
|
||||||
|
|
||||||
import curses
|
|
||||||
import shared
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import StringIO
|
import StringIO
|
||||||
|
|
||||||
|
import time
|
||||||
|
from time import strftime, localtime
|
||||||
|
from threading import Timer
|
||||||
|
|
||||||
|
import curses
|
||||||
|
import dialog
|
||||||
|
from dialog import Dialog
|
||||||
|
|
||||||
|
import shared
|
||||||
|
import ConfigParser
|
||||||
from addresses import *
|
from addresses import *
|
||||||
|
|
||||||
quit = False
|
quit = False
|
||||||
menutab = 1
|
menutab = 1
|
||||||
menu = ["Inbox", "Send", "Sent", "Your Identities", "Subscriptions", "Address Book", "Blacklist", "Network Status"]
|
menu = ["Inbox", "Send", "Sent", "Your Identities", "Subscriptions", "Address Book", "Blacklist", "Network Status"]
|
||||||
log = ""
|
log = ""
|
||||||
|
logpad = None
|
||||||
|
inventorydata = 0
|
||||||
|
|
||||||
|
startuptime = time.time()
|
||||||
addresses = []
|
addresses = []
|
||||||
addrcur = 0
|
addrcur = 0
|
||||||
|
addrcopy = 0
|
||||||
|
|
||||||
class printLog:
|
class printLog:
|
||||||
def write(self, output):
|
def write(self, output):
|
||||||
global log
|
global log
|
||||||
log += output
|
log += output
|
||||||
|
def flush(self):
|
||||||
|
pass
|
||||||
|
class errLog:
|
||||||
|
def write(self, output):
|
||||||
|
global log
|
||||||
|
log += "!"+output
|
||||||
|
def flush(self):
|
||||||
|
pass
|
||||||
printlog = printLog()
|
printlog = printLog()
|
||||||
|
errlog = errLog()
|
||||||
|
|
||||||
|
|
||||||
def cpair(a):
|
def cpair(a):
|
||||||
r = curses.color_pair(a)
|
r = curses.color_pair(a)
|
||||||
|
@ -42,18 +69,81 @@ def drawmenu(stdscr):
|
||||||
menustr += " "
|
menustr += " "
|
||||||
stdscr.addstr(2, 5, menustr, curses.A_UNDERLINE)
|
stdscr.addstr(2, 5, menustr, curses.A_UNDERLINE)
|
||||||
|
|
||||||
|
def resetlookups():
|
||||||
|
inventorydata = shared.numberOfInventoryLookupsPerformed
|
||||||
|
shared.numberOfInventoryLookupsPerformed = 0
|
||||||
|
Timer(2, resetlookups, ()).start()
|
||||||
def drawtab(stdscr):
|
def drawtab(stdscr):
|
||||||
if menutab in range(0, len(menu)):
|
if menutab in range(1, len(menu)+1):
|
||||||
if menutab == 1: # Inbox
|
if menutab == 1: # Inbox
|
||||||
stdscr.addstr(3, 5, "new messages")
|
pass
|
||||||
elif menutab == 2: # Send
|
elif menutab == 2: # Send
|
||||||
stdscr.addstr(3, 5, "to: from:")
|
pass
|
||||||
|
elif menutab == 3: # Sent
|
||||||
|
pass
|
||||||
elif menutab == 4: # Identities
|
elif menutab == 4: # Identities
|
||||||
|
stdscr.addstr(3, 5, "Label", curses.A_BOLD)
|
||||||
|
stdscr.addstr(3, 50, "Address", curses.A_BOLD)
|
||||||
|
stdscr.addstr(3, 100, "Stream", curses.A_BOLD)
|
||||||
for i, item in enumerate(addresses):
|
for i, item in enumerate(addresses):
|
||||||
a = 0
|
a = 0
|
||||||
if i == addrcur:
|
if i == addrcur: # Highlight current address
|
||||||
a = curses.A_REVERSE
|
a = a | curses.A_REVERSE
|
||||||
stdscr.addstr(3+i, 5, item[0], cpair(item[3]) | a)
|
if item[1] == True and item[3] not in [8,9]: # Embolden enabled, non-special addresses
|
||||||
|
a = a | curses.A_BOLD
|
||||||
|
stdscr.addstr(4+i, 5, item[0], a)
|
||||||
|
stdscr.addstr(4+i, 50, item[2], cpair(item[3]) | a)
|
||||||
|
stdscr.addstr(4+i, 100, str(1), a)
|
||||||
|
elif menutab == 5: # Subscriptions
|
||||||
|
pass
|
||||||
|
elif menutab == 6: # Address book
|
||||||
|
pass
|
||||||
|
elif menutab == 7: # Blacklist
|
||||||
|
pass
|
||||||
|
elif menutab == 8: # Network status
|
||||||
|
# Connection data
|
||||||
|
stdscr.addstr(4, 5, "Total Connections: "+str(len(shared.connectedHostsList)).ljust(2))
|
||||||
|
stdscr.addstr(6, 6, "Stream #", curses.A_BOLD)
|
||||||
|
stdscr.addstr(6, 17, "Connections", curses.A_BOLD)
|
||||||
|
streamcount = []
|
||||||
|
for host, stream in shared.connectedHostsList.items():
|
||||||
|
if stream >= len(streamcount):
|
||||||
|
streamcount.append(1)
|
||||||
|
else:
|
||||||
|
streamcount[stream] += 1
|
||||||
|
for i, item in enumerate(streamcount):
|
||||||
|
if i < 5:
|
||||||
|
if i == 0:
|
||||||
|
stdscr.addstr(7+i, 6, "?")
|
||||||
|
else:
|
||||||
|
stdscr.addstr(7+i, 6, str(i))
|
||||||
|
stdscr.addstr(7+i, 17, str(item))
|
||||||
|
|
||||||
|
# Uptime and processing data
|
||||||
|
stdscr.addstr(6, 35, "Since startup on "+unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(startuptime)))))
|
||||||
|
stdscr.addstr(7, 40, "Processed "+str(shared.numberOfMessagesProcessed).ljust(4)+" person-to-person messages.")
|
||||||
|
stdscr.addstr(8, 40, "Processed "+str(shared.numberOfBroadcastsProcessed).ljust(4)+" broadcast messages.")
|
||||||
|
stdscr.addstr(9, 40, "Processed "+str(shared.numberOfPubkeysProcessed).ljust(4)+" public keys.")
|
||||||
|
|
||||||
|
# Inventory data
|
||||||
|
stdscr.addstr(11, 35, "Inventory lookups per second: "+str(int(inventorydata/2)).ljust(3))
|
||||||
|
|
||||||
|
# Log
|
||||||
|
stdscr.addstr(13, 6, "Log", curses.A_BOLD)
|
||||||
|
n = log.count('\n')
|
||||||
|
if n > 0:
|
||||||
|
l = log.split('\n')
|
||||||
|
if n > 512:
|
||||||
|
del l[:(n-256)]
|
||||||
|
logpad.erase()
|
||||||
|
n = len(l)
|
||||||
|
for i, item in enumerate(l):
|
||||||
|
a = 0
|
||||||
|
if len(item) > 0 and item[0] == '!':
|
||||||
|
a = curses.color_pair(1)
|
||||||
|
item = item[1:]
|
||||||
|
logpad.addstr(i, 0, item, a)
|
||||||
|
logpad.refresh(n-curses.LINES+2, 0, 14, 6, curses.LINES-2, curses.COLS-7)
|
||||||
stdscr.refresh()
|
stdscr.refresh()
|
||||||
|
|
||||||
def redraw(stdscr):
|
def redraw(stdscr):
|
||||||
|
@ -61,6 +151,10 @@ def redraw(stdscr):
|
||||||
stdscr.border()
|
stdscr.border()
|
||||||
drawmenu(stdscr)
|
drawmenu(stdscr)
|
||||||
stdscr.refresh()
|
stdscr.refresh()
|
||||||
|
def dialogreset(stdscr):
|
||||||
|
stdscr.clear()
|
||||||
|
stdscr.keypad(1)
|
||||||
|
curses.curs_set(0)
|
||||||
def handlech(c, stdscr):
|
def handlech(c, stdscr):
|
||||||
if c != curses.ERR:
|
if c != curses.ERR:
|
||||||
if c in range(256):
|
if c in range(256):
|
||||||
|
@ -70,20 +164,176 @@ def handlech(c, stdscr):
|
||||||
elif chr(c) == 'q':
|
elif chr(c) == 'q':
|
||||||
global quit
|
global quit
|
||||||
quit = True
|
quit = True
|
||||||
|
elif chr(c) == '\n':
|
||||||
|
if menutab == 4:
|
||||||
|
curses.curs_set(1)
|
||||||
|
d = Dialog(dialog="dialog")
|
||||||
|
d.set_background_title("Your Identities Dialog Box")
|
||||||
|
r, t = d.menu("Do what with \""+addresses[addrcur][0]+"\" : \""+addresses[addrcur][2]+"\"?",
|
||||||
|
choices=[("1", "Create new address"),
|
||||||
|
("2", "Copy address to internal buffer"),
|
||||||
|
("3", "Rename"),
|
||||||
|
("4", "Enable"),
|
||||||
|
("5", "Disable"),
|
||||||
|
("6", "Delete"),
|
||||||
|
("7", "Special address behavior")])
|
||||||
|
if r == d.DIALOG_OK:
|
||||||
|
if t == "1": # Create new address
|
||||||
|
d.set_background_title("Create new address")
|
||||||
|
d.scrollbox(unicode("Here you may generate as many addresses as you like.\n"
|
||||||
|
"Indeed, creating and abandoning addresses is encouraged.\n"
|
||||||
|
"Deterministic addresses have several pros and cons:\n"
|
||||||
|
"\nPros:\n"
|
||||||
|
" * You can recreate your addresses on any computer from memory\n"
|
||||||
|
" * You need not worry about backing up your keys.dat file as long as you \n can remember your passphrase\n"
|
||||||
|
"Cons:\n"
|
||||||
|
" * You must remember (or write down) your passphrase in order to recreate \n your keys if they are lost\n"
|
||||||
|
" * You must also remember the address version and stream numbers\n"
|
||||||
|
" * If you choose a weak passphrase someone may be able to brute-force it \n and then send and receive messages as you"),
|
||||||
|
exit_label="Continue")
|
||||||
|
r, t = d.menu("Choose an address generation technique",
|
||||||
|
choices=[("1", "Use a random number generator"),
|
||||||
|
("2", "Use a passphrase")])
|
||||||
|
if r == d.DIALOG_OK:
|
||||||
|
if t == "1":
|
||||||
|
d.set_background_title("Randomly generate address")
|
||||||
|
r, t = d.inputbox("Label (not shown to anyone except you)")
|
||||||
|
label = ""
|
||||||
|
if r == d.DIALOG_OK and len(t) > 0:
|
||||||
|
label = t
|
||||||
|
r, t = d.menu("Choose a stream",
|
||||||
|
choices=[("1", "Use the most available stream"),("", "(Best if this is the first of many addresses you will create)"),
|
||||||
|
("2", "Use the same stream as an existing address"),("", "(Saves you some bandwidth and processing power)")])
|
||||||
|
if r == d.DIALOG_OK:
|
||||||
|
if t == "1":
|
||||||
|
stream = 1
|
||||||
|
elif t == "2":
|
||||||
|
addrs = []
|
||||||
|
for i, item in enumerate(addresses):
|
||||||
|
addrs.append([str(i), item[2]])
|
||||||
|
r, t = d.menu("Choose an existing address's stream", choices=addrs)
|
||||||
|
if r == d.DIALOG_OK:
|
||||||
|
stream = decodeAddress(addrs[int(t)][1])[2]
|
||||||
|
shorten = False
|
||||||
|
r, t = d.checklist("Miscellaneous options",
|
||||||
|
choices=[("1", "Spend time shortening the address", shorten)])
|
||||||
|
if r == d.DIALOG_OK and "1" in t:
|
||||||
|
shorten = True
|
||||||
|
shared.addressGeneratorQueue.put(("createRandomAddress", 4, stream, label, 1, "", shorten))
|
||||||
|
elif t == "2":
|
||||||
|
d.set_background_title("Make deterministic addresses")
|
||||||
|
r, t = d.passwordform("Enter passphrase",
|
||||||
|
[("Passphrase", 1, 1, "", 2, 1, 64, 128),
|
||||||
|
("Confirm passphrase", 3, 1, "", 4, 1, 64, 128)],
|
||||||
|
form_height=4, insecure=True)
|
||||||
|
if r == d.DIALOG_OK:
|
||||||
|
if t[0] == t[1]:
|
||||||
|
passphrase = t[0]
|
||||||
|
r, t = d.rangebox("Number of addresses to generate",
|
||||||
|
width=48, min=1, max=99, init=8)
|
||||||
|
if r == d.DIALOG_OK:
|
||||||
|
number = t
|
||||||
|
stream = 1
|
||||||
|
shorten = False
|
||||||
|
r, t = d.checklist("Miscellaneous options",
|
||||||
|
choices=[("1", "Spend time shortening the address", shorten)])
|
||||||
|
if r == d.DIALOG_OK and "1" in t:
|
||||||
|
shorten = True
|
||||||
|
d.scrollbox(unicode("In addition to your passphrase, be sure to remember the following numbers:\n"
|
||||||
|
"\n * Address version number: "+str(4)+"\n"
|
||||||
|
" * Stream number: "+str(stream)),
|
||||||
|
exit_label="Continue")
|
||||||
|
shared.addressGeneratorQueue.put(('createDeterministicAddresses', 4, stream, "unused deterministic address", number, str(passphrase), shorten))
|
||||||
|
else:
|
||||||
|
d.scrollbox(unicode("Passphrases do not match"), exit_label="Continue")
|
||||||
|
elif t == "2": # Copy address to internal buffer
|
||||||
|
addrcopy = addrcur
|
||||||
|
elif t == "3": # Rename address label
|
||||||
|
a = addresses[addrcur][2]
|
||||||
|
label = addresses[addrcur][0]
|
||||||
|
r, t = d.inputbox("New address label", init=label)
|
||||||
|
if r == d.DIALOG_OK:
|
||||||
|
label = t
|
||||||
|
shared.config.set(a, "label", label)
|
||||||
|
# Write config
|
||||||
|
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
|
||||||
|
shared.config.write(configfile)
|
||||||
|
addresses[addrcur][0] = label
|
||||||
|
elif t == "4": # Enable address
|
||||||
|
a = addresses[addrcur][2]
|
||||||
|
shared.config.set(a, "enabled", "true") # Set config
|
||||||
|
# Write config
|
||||||
|
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
|
||||||
|
shared.config.write(configfile)
|
||||||
|
# Change color
|
||||||
|
if shared.safeConfigGetBoolean(a, 'chan'):
|
||||||
|
addresses[addrcur][3] = 9 # orange
|
||||||
|
elif shared.safeConfigGetBoolean(a, 'mailinglist'):
|
||||||
|
addresses[addrcur][3] = 5 # magenta
|
||||||
|
else:
|
||||||
|
addresses[addrcur][3] = 0 # black
|
||||||
|
addresses[addrcur][1] = True
|
||||||
|
shared.reloadMyAddressHashes() # Reload address hashes
|
||||||
|
elif t == "5": # Disable address
|
||||||
|
a = addresses[addrcur][2]
|
||||||
|
shared.config.set(a, "enabled", "false") # Set config
|
||||||
|
addresses[addrcur][3] = 8 # Set color to gray
|
||||||
|
# Write config
|
||||||
|
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
|
||||||
|
shared.config.write(configfile)
|
||||||
|
addresses[addrcur][1] = False
|
||||||
|
shared.reloadMyAddressHashes() # Reload address hashes
|
||||||
|
elif t == "6": # Delete address
|
||||||
|
pass
|
||||||
|
elif t == "7": # Special address behavior
|
||||||
|
a = addresses[addrcur][2]
|
||||||
|
d.set_background_title("Special address behavior")
|
||||||
|
if shared.safeConfigGetBoolean(a, "chan"):
|
||||||
|
d.scrollbox(unicode("This is a chan address. You cannot use it as a pseudo-mailing list."), exit_label="Continue")
|
||||||
|
else:
|
||||||
|
m = shared.safeConfigGetBoolean(a, "mailinglist")
|
||||||
|
r, t = d.radiolist("Select address behavior",
|
||||||
|
choices=[("1", "Behave as a normal address", not m), ("2", "Behave as a pseudo-mailing-list address", m)])
|
||||||
|
if r == d.DIALOG_OK:
|
||||||
|
if t == "1" and m == True:
|
||||||
|
shared.config.set(a, "mailinglist", "false")
|
||||||
|
if addresses[addrcur][1]:
|
||||||
|
addresses[addrcur][3] = 0 # Set color to black
|
||||||
|
else:
|
||||||
|
addresses[addrcur][3] = 8 # Set color to gray
|
||||||
|
elif t == "2" and m == False:
|
||||||
|
try:
|
||||||
|
mn = shared.config.get(a, "mailinglistname")
|
||||||
|
except ConfigParser.NoOptionError:
|
||||||
|
mn = ""
|
||||||
|
r, t = d.inputbox("Mailing list name", init=mn)
|
||||||
|
if r == d.DIALOG_OK:
|
||||||
|
mn = t
|
||||||
|
shared.config.set(a, "mailinglist", "true")
|
||||||
|
shared.config.set(a, "mailinglistname", mn)
|
||||||
|
addresses[addrcur][3] = 6 # Set color to magenta
|
||||||
|
# Write config
|
||||||
|
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
|
||||||
|
shared.config.write(configfile)
|
||||||
|
dialogreset(stdscr)
|
||||||
else:
|
else:
|
||||||
global addrcur
|
global addrcur
|
||||||
if c == curses.KEY_UP:
|
if c == curses.KEY_UP:
|
||||||
if (addrcur > 0):
|
if menutab == 4 and addrcur > 0:
|
||||||
addrcur -= 1
|
addrcur -= 1
|
||||||
elif c == curses.KEY_DOWN:
|
elif c == curses.KEY_DOWN:
|
||||||
if (addrcur < len(addresses)-1):
|
if menutab == 4 and addrcur < len(addresses)-1:
|
||||||
addrcur += 1
|
addrcur += 1
|
||||||
redraw(stdscr)
|
redraw(stdscr)
|
||||||
|
|
||||||
def runwrapper():
|
def runwrapper():
|
||||||
sys.stdout = printlog
|
sys.stdout = printlog
|
||||||
|
sys.stderr = errlog
|
||||||
stdscr = curses.initscr()
|
stdscr = curses.initscr()
|
||||||
|
|
||||||
|
global logpad
|
||||||
|
logpad = curses.newpad(1024, curses.COLS)
|
||||||
|
|
||||||
stdscr.nodelay(1)
|
stdscr.nodelay(1)
|
||||||
curses.curs_set(0)
|
curses.curs_set(0)
|
||||||
curses.start_color()
|
curses.start_color()
|
||||||
|
@ -92,29 +342,43 @@ def runwrapper():
|
||||||
shutdown()
|
shutdown()
|
||||||
|
|
||||||
def run(stdscr):
|
def run(stdscr):
|
||||||
# Init list of address in 'Your Identities' tab
|
# Schedule inventory lookup data
|
||||||
configSections = shared.config.sections()
|
resetlookups()
|
||||||
|
|
||||||
|
# Init color pairs
|
||||||
if curses.has_colors():
|
if curses.has_colors():
|
||||||
curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK) # red
|
curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK) # red
|
||||||
|
curses.init_pair(2, curses.COLOR_GREEN, curses.COLOR_BLACK) # green
|
||||||
|
curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLACK) # yellow
|
||||||
|
curses.init_pair(4, curses.COLOR_BLUE, curses.COLOR_BLACK) # blue
|
||||||
|
curses.init_pair(5, curses.COLOR_MAGENTA, curses.COLOR_BLACK) # magenta
|
||||||
|
curses.init_pair(6, curses.COLOR_CYAN, curses.COLOR_BLACK) # cyan
|
||||||
|
curses.init_pair(7, curses.COLOR_WHITE, curses.COLOR_BLACK) # white
|
||||||
if curses.can_change_color():
|
if curses.can_change_color():
|
||||||
curses.init_color(8, 500, 500, 500) # gray
|
curses.init_color(8, 500, 500, 500) # gray
|
||||||
curses.init_pair(8, 8, 0)
|
curses.init_pair(8, 8, 0)
|
||||||
curses.init_color(9, 844, 465, 0) # orange
|
curses.init_color(9, 844, 465, 0) # orange
|
||||||
curses.init_pair(9, 9, 0)
|
curses.init_pair(9, 9, 0)
|
||||||
else:
|
else:
|
||||||
global menutab
|
curses.init_pair(8, curses.COLOR_WHITE, curses.COLOR_BLACK) # grayish
|
||||||
menutab = 4
|
curses.init_pair(9, curses.COLOR_YELLOW, curses.COLOR_BLACK) # orangish
|
||||||
curses.beep()
|
|
||||||
|
# Init list of address in 'Your Identities' tab
|
||||||
|
configSections = shared.config.sections()
|
||||||
for addressInKeysFile in configSections:
|
for addressInKeysFile in configSections:
|
||||||
if addressInKeysFile != "bitmessagesettings":
|
if addressInKeysFile != "bitmessagesettings":
|
||||||
isEnabled = shared.config.getboolean(addressInKeysFile, "enabled")
|
isEnabled = shared.config.getboolean(addressInKeysFile, "enabled")
|
||||||
addresses.append([shared.config.get(addressInKeysFile, "label"), isEnabled, str(decodeAddress(addressInKeysFile)[2])])
|
addresses.append([shared.config.get(addressInKeysFile, "label"), isEnabled, addressInKeysFile])
|
||||||
|
# Set address color
|
||||||
if not isEnabled:
|
if not isEnabled:
|
||||||
addresses[len(addresses)-1].append(8) # gray
|
addresses[len(addresses)-1].append(8) # gray
|
||||||
elif shared.safeConfigGetBoolean(addressInKeysFile, 'chan'):
|
elif shared.safeConfigGetBoolean(addressInKeysFile, 'chan'):
|
||||||
addresses[len(addresses)-1].append(9) # orange
|
addresses[len(addresses)-1].append(9) # orange
|
||||||
elif shared.safeConfigGetBoolean(addressInKeysFile, 'mailinglist'):
|
elif shared.safeConfigGetBoolean(addressInKeysFile, 'mailinglist'):
|
||||||
addresses[len(addresses)-1].append(5) # magenta
|
addresses[len(addresses)-1].append(5) # magenta
|
||||||
|
else:
|
||||||
|
addresses[len(addresses)-1].append(0) # black
|
||||||
|
addresses.reverse()
|
||||||
|
|
||||||
# Load messages from database
|
# Load messages from database
|
||||||
"""
|
"""
|
||||||
|
@ -140,5 +404,6 @@ def shutdown():
|
||||||
sys.stdout = printlog
|
sys.stdout = printlog
|
||||||
shared.doCleanShutdown()
|
shared.doCleanShutdown()
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
|
sys.stderr = sys.__stderr__
|
||||||
|
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python2.7
|
||||||
# Copyright (c) 2012 Jonathan Warren
|
# Copyright (c) 2012 Jonathan Warren
|
||||||
# Copyright (c) 2012 The Bitmessage developers
|
# Copyright (c) 2012 The Bitmessage developers
|
||||||
# Distributed under the MIT/X11 software license. See the accompanying
|
# Distributed under the MIT/X11 software license. See the accompanying
|
||||||
|
@ -99,6 +99,11 @@ class Main:
|
||||||
# is the application already running? If yes then exit.
|
# is the application already running? If yes then exit.
|
||||||
thisapp = singleton.singleinstance()
|
thisapp = singleton.singleinstance()
|
||||||
|
|
||||||
|
# get curses flag
|
||||||
|
curses = False
|
||||||
|
if '-c' in sys.argv:
|
||||||
|
curses = True
|
||||||
|
|
||||||
signal.signal(signal.SIGINT, helper_generic.signal_handler)
|
signal.signal(signal.SIGINT, helper_generic.signal_handler)
|
||||||
# signal.signal(signal.SIGINT, signal.SIG_DFL)
|
# signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||||
|
|
||||||
|
@ -159,10 +164,16 @@ class Main:
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print 'PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can download PyQt from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for \'PyQt Download\'. If you want to run in daemon mode, see https://bitmessage.org/wiki/Daemon'
|
print 'PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can download PyQt from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for \'PyQt Download\'. If you want to run in daemon mode, see https://bitmessage.org/wiki/Daemon'
|
||||||
print 'Error message:', err
|
print 'Error message:', err
|
||||||
|
print 'You can also run PyBitmessage with the new curses interface by providing \'-c\' as a commandline argument.'
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
|
|
||||||
|
if curses == False:
|
||||||
import bitmessageqt
|
import bitmessageqt
|
||||||
bitmessageqt.run()
|
bitmessageqt.run()
|
||||||
|
else:
|
||||||
|
print 'Running with curses'
|
||||||
|
import bitmessagecurses
|
||||||
|
bitmessagecurses.runwrapper()
|
||||||
else:
|
else:
|
||||||
shared.config.remove_option('bitmessagesettings', 'dontconnect')
|
shared.config.remove_option('bitmessagesettings', 'dontconnect')
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ Use: `from debug import logger` to import this facility into whatever module you
|
||||||
import logging
|
import logging
|
||||||
import logging.config
|
import logging.config
|
||||||
import shared
|
import shared
|
||||||
|
import sys
|
||||||
|
|
||||||
# TODO(xj9): Get from a config file.
|
# TODO(xj9): Get from a config file.
|
||||||
log_level = 'DEBUG'
|
log_level = 'DEBUG'
|
||||||
|
@ -69,6 +70,9 @@ def configureLogging():
|
||||||
# TODO (xj9): Get from a config file.
|
# TODO (xj9): Get from a config file.
|
||||||
#logger = logging.getLogger('console_only')
|
#logger = logging.getLogger('console_only')
|
||||||
configureLogging()
|
configureLogging()
|
||||||
|
if '-c' in sys.argv:
|
||||||
|
logger = logging.getLogger('file_only')
|
||||||
|
else:
|
||||||
logger = logging.getLogger('both')
|
logger = logging.getLogger('both')
|
||||||
|
|
||||||
def restartLoggingInUpdatedAppdataLocation():
|
def restartLoggingInUpdatedAppdataLocation():
|
||||||
|
@ -78,4 +82,8 @@ def restartLoggingInUpdatedAppdataLocation():
|
||||||
i.flush()
|
i.flush()
|
||||||
i.close()
|
i.close()
|
||||||
configureLogging()
|
configureLogging()
|
||||||
|
if '-c' in sys.argv:
|
||||||
|
logger = logging.getLogger('file_only')
|
||||||
|
else:
|
||||||
logger = logging.getLogger('both')
|
logger = logging.getLogger('both')
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user