4 from __future__ import with_statement
12 from PyQt4 import QtGui
13 from PyQt4 import QtCore
17 from util import qtpie
18 from util import misc as misc_utils
21 _moduleLogger = logging.getLogger(__name__)
27 class Dialcentral(object):
30 os.path.dirname(__file__),
31 os.path.join(os.path.dirname(__file__), "../data"),
32 os.path.join(os.path.dirname(__file__), "../lib"),
33 '/usr/share/%s' % constants.__app_name__,
34 '/usr/lib/%s' % constants.__app_name__,
37 def __init__(self, app):
40 self._hiddenCategories = set()
41 self._hiddenUnits = {}
42 self._clipboard = QtGui.QApplication.clipboard()
44 self._mainWindow = None
46 self._fullscreenAction = QtGui.QAction(None)
47 self._fullscreenAction.setText("Fullscreen")
48 self._fullscreenAction.setCheckable(True)
49 self._fullscreenAction.setShortcut(QtGui.QKeySequence("CTRL+Enter"))
50 self._fullscreenAction.toggled.connect(self._on_toggle_fullscreen)
52 self._logAction = QtGui.QAction(None)
53 self._logAction.setText("Log")
54 self._logAction.setShortcut(QtGui.QKeySequence("CTRL+l"))
55 self._logAction.triggered.connect(self._on_log)
57 self._quitAction = QtGui.QAction(None)
58 self._quitAction.setText("Quit")
59 self._quitAction.setShortcut(QtGui.QKeySequence("CTRL+q"))
60 self._quitAction.triggered.connect(self._on_quit)
62 self._app.lastWindowClosed.connect(self._on_app_quit)
65 self._mainWindow = MainWindow(None, self)
66 self._mainWindow.window.destroyed.connect(self._on_child_close)
68 def load_settings(self):
70 with open(constants._user_settings_, "r") as settingsFile:
71 settings = simplejson.load(settingsFile)
73 _moduleLogger.info("No settings")
76 _moduleLogger.info("Settings were corrupt")
79 self._fullscreenAction.setChecked(settings.get("isFullScreen", False))
81 def save_settings(self):
83 "isFullScreen": self._fullscreenAction.isChecked(),
85 with open(constants._user_settings_, "w") as settingsFile:
86 simplejson.dump(settings, settingsFile)
89 def fullscreenAction(self):
90 return self._fullscreenAction
94 return self._logAction
98 return self._quitAction
100 def _close_windows(self):
101 if self._mainWindow is not None:
102 self._mainWindow.window.destroyed.disconnect(self._on_child_close)
103 self._mainWindow.close()
104 self._mainWindow = None
106 @misc_utils.log_exception(_moduleLogger)
107 def _on_app_quit(self, checked = False):
110 @misc_utils.log_exception(_moduleLogger)
111 def _on_child_close(self, obj = None):
112 self._mainWindow = None
114 @misc_utils.log_exception(_moduleLogger)
115 def _on_toggle_fullscreen(self, checked = False):
116 for window in self._walk_children():
117 window.set_fullscreen(checked)
119 @misc_utils.log_exception(_moduleLogger)
120 def _on_log(self, checked = False):
121 with open(constants._user_logpath_, "r") as f:
122 logLines = f.xreadlines()
123 log = "".join(logLines)
124 self._clipboard.setText(log)
126 @misc_utils.log_exception(_moduleLogger)
127 def _on_quit(self, checked = False):
128 self._close_windows()
131 class QErrorDisplay(object):
136 errorIcon = maeqt.get_theme_icon(("dialog-error", "app_install_error", "gtk-dialog-error"))
137 self._severityIcon = errorIcon.pixmap(32, 32)
138 self._severityLabel = QtGui.QLabel()
139 self._severityLabel.setPixmap(self._severityIcon)
141 self._message = QtGui.QLabel()
142 self._message.setText("Boo")
144 closeIcon = maeqt.get_theme_icon(("window-close", "general_close", "gtk-close"))
145 self._closeLabel = QtGui.QPushButton(closeIcon, "")
146 self._closeLabel.clicked.connect(self._on_close)
148 self._controlLayout = QtGui.QHBoxLayout()
149 self._controlLayout.addWidget(self._severityLabel)
150 self._controlLayout.addWidget(self._message)
151 self._controlLayout.addWidget(self._closeLabel)
153 self._topLevelLayout = QtGui.QHBoxLayout()
154 self._topLevelLayout.addLayout(self._controlLayout)
155 self._widget = QtGui.QWidget()
156 self._widget.setLayout(self._topLevelLayout)
163 def push_message(self, message):
164 self._messages.append(message)
165 if 1 == len(self._messages):
166 self._show_message(message)
168 def push_exception(self):
169 userMessage = str(sys.exc_info()[1])
170 _moduleLogger.exception(userMessage)
171 self.push_message(userMessage)
173 def pop_message(self):
174 del self._messages[0]
175 if 0 == len(self._messages):
178 self._message.setText(self._messages[0])
180 def _on_close(self, *args):
183 def _show_message(self, message):
184 self._message.setText(message)
187 def _hide_message(self):
188 self._message.setText("")
192 class CredentialsDialog(object):
195 self._usernameField = QtGui.QLineEdit()
196 self._passwordField = QtGui.QLineEdit()
197 self._passwordField.setEchoMode(QtGui.QLineEdit.PasswordEchoOnEdit)
199 self._credLayout = QtGui.QGridLayout()
200 self._credLayout.addWidget(QtGui.QLabel("Username"), 0, 0)
201 self._credLayout.addWidget(self._usernameField, 0, 1)
202 self._credLayout.addWidget(QtGui.QLabel("Password"), 1, 0)
203 self._credLayout.addWidget(self._passwordField, 1, 1)
205 self._loginButton = QtGui.QPushButton("&Login")
206 self._buttonLayout = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Cancel)
207 self._buttonLayout.addButton(self._loginButton, QtGui.QDialogButtonBox.AcceptRole)
209 self._layout = QtGui.QVBoxLayout()
210 self._layout.addLayout(self._credLayout)
211 self._layout.addLayout(self._buttonLayout)
213 centralWidget = QtGui.QWidget()
214 centralWidget.setLayout(self._layout)
216 self._dialog = QtGui.QDialog()
217 self._dialog.setWindowTitle("Login")
218 self._dialog.setCentralWidget(centralWidget)
219 maeqt.set_autorient(self._dialog, True)
220 self._buttonLayout.accepted.connect(self._dialog.accept)
221 self._buttonLayout.rejected.connect(self._dialog.reject)
223 def run(self, defaultUsername, defaultPassword, parent=None):
224 self._dialog.setParent(parent)
225 self._usernameField.setText(defaultUsername)
226 self._passwordField.setText(defaultPassword)
228 response = self._dialog.exec_()
229 if response == QtGui.QDialog.Accepted:
230 return str(self._usernameField.text()), str(self._passwordField.text())
231 elif response == QtGui.QDialog.Rejected:
232 raise RuntimeError("Login Cancelled")
235 class AccountDialog(object):
238 self._accountNumberLabel = QtGui.QLabel("NUMBER NOT SET")
239 self._clearButton = QtGui.QPushButton("Clear Account")
240 self._clearButton.clicked.connect(self._on_clear)
241 self._doClear = False
243 self._credLayout = QtGui.QGridLayout()
244 self._credLayout.addWidget(QtGui.QLabel("Account"), 0, 0)
245 self._credLayout.addWidget(self._accountNumberLabel, 0, 1)
246 self._credLayout.addWidget(QtGui.QLabel("Callback"), 1, 0)
247 self._credLayout.addWidget(self._clearButton, 2, 1)
249 self._loginButton = QtGui.QPushButton("&Login")
250 self._buttonLayout = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Cancel)
251 self._buttonLayout.addButton(self._loginButton, QtGui.QDialogButtonBox.AcceptRole)
253 self._layout = QtGui.QVBoxLayout()
254 self._layout.addLayout(self._credLayout)
255 self._layout.addLayout(self._buttonLayout)
257 centralWidget = QtGui.QWidget()
258 centralWidget.setLayout(self._layout)
260 self._dialog = QtGui.QDialog()
261 self._dialog.setWindowTitle("Login")
262 self._dialog.setCentralWidget(centralWidget)
263 maeqt.set_autorient(self._dialog, True)
264 self._buttonLayout.accepted.connect(self._dialog.accept)
265 self._buttonLayout.rejected.connect(self._dialog.reject)
271 accountNumber = property(
272 lambda self: str(self._accountNumberLabel.text()),
273 lambda self, num: self._accountNumberLabel.setText(num),
276 def run(self, defaultUsername, defaultPassword, parent=None):
277 self._doClear = False
278 self._dialog.setParent(parent)
279 self._usernameField.setText(defaultUsername)
280 self._passwordField.setText(defaultPassword)
282 response = self._dialog.exec_()
283 if response == QtGui.QDialog.Accepted:
284 return str(self._usernameField.text()), str(self._passwordField.text())
285 elif response == QtGui.QDialog.Rejected:
286 raise RuntimeError("Login Cancelled")
288 def _on_clear(self, checked = False):
290 self._dialog.accept()
293 class SMSEntryWindow(object):
295 def __init__(self, parent, app):
299 self._history = QtGui.QListView()
300 self._smsEntry = QtGui.QTextEdit()
301 self._smsEntry.textChanged.connect(self._on_letter_count_changed)
303 self._entryLayout = QtGui.QVBoxLayout()
304 self._entryLayout.addWidget(self._history)
305 self._entryLayout.addWidget(self._smsEntry)
306 self._entryWidget = QtGui.QWidget()
307 self._entryWidget.setLayout(self._entryLayout)
308 self._scrollEntry = QtGui.QScrollArea()
309 self._scrollEntry.setWidget(self._entryWidget)
310 self._scrollEntry.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignBottom)
311 self._scrollEntry.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
312 self._scrollEntry.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
314 self._characterCountLabel = QtGui.QLabel("Letters: %s" % 0)
315 self._numberSelector = None
316 self._smsButton = QtGui.QPushButton("SMS")
317 self._dialButton = QtGui.QPushButton("Dial")
319 self._buttonLayout = QtGui.QHBoxLayout()
320 self._buttonLayout.addWidget(self._characterCountLabel)
321 self._buttonLayout.addWidget(self._smsButton)
322 self._buttonLayout.addWidget(self._dialButton)
324 self._layout = QtGui.QVBoxLayout()
325 self._layout.addLayout(self._entryLayout)
326 self._layout.addLayout(self._buttonLayout)
328 centralWidget = QtGui.QWidget()
329 centralWidget.setLayout(self._layout)
331 self._window = QtGui.QMainWindow(parent)
332 self._window.setAttribute(QtCore.Qt.WA_DeleteOnClose, False)
333 maeqt.set_autorient(self._window, True)
334 maeqt.set_stackable(self._window, True)
335 self._window.setWindowTitle("Contact")
336 self._window.setCentralWidget(centralWidget)
338 def _update_letter_count(self):
339 count = self._smsEntry.toPlainText().size()
340 self._characterCountLabel.setText("Letters: %s" % count)
342 def _update_button_state(self):
343 if len(self._contacts) == 0:
344 self._dialButton.setEnabled(False)
345 self._smsButton.setEnabled(False)
346 elif len(self._contacts) == 1:
347 count = self._smsEntry.toPlainText().size()
349 self._dialButton.setEnabled(True)
350 self._smsButton.setEnabled(False)
352 self._dialButton.setEnabled(False)
353 self._smsButton.setEnabled(True)
355 self._dialButton.setEnabled(False)
356 self._smsButton.setEnabled(True)
358 def _on_letter_count_changed(self):
359 self._update_letter_count()
360 self._update_button_state()
363 class DelayedWidget(object):
365 def __init__(self, app):
366 self._layout = QtGui.QVBoxLayout()
367 self._widget = QtGui.QWidget()
368 self._widget.setLayout(self._layout)
371 self._isEnabled = True
378 return self._child is not None
380 def set_child(self, child):
381 if self._child is not None:
382 self._layout.removeWidget(self._child.toplevel)
384 if self._child is not None:
385 self._layout.addWidget(self._child.toplevel)
390 self._child.disable()
393 self._isEnabled = True
394 if self._child is not None:
398 self._isEnabled = False
399 if self._child is not None:
400 self._child.disable()
403 if self._child is not None:
404 self._child.refresh()
407 class Dialpad(object):
409 def __init__(self, app):
412 self._plus = self._generate_key_button("+", "")
413 self._entry = QtGui.QLineEdit()
415 backAction = QtGui.QAction(None)
416 backAction.setText("Back")
417 backAction.triggered.connect(self._on_backspace)
418 backPieItem = qtpie.QActionPieItem(backAction)
419 clearAction = QtGui.QAction(None)
420 clearAction.setText("Clear")
421 clearAction.triggered.connect(self._on_clear_text)
422 clearPieItem = qtpie.QActionPieItem(clearAction)
423 self._back = qtpie.QPieButton(backPieItem)
424 self._back.set_center(backPieItem)
425 self._back.insertItem(qtpie.PieFiling.NULL_CENTER)
426 self._back.insertItem(clearPieItem)
427 self._back.insertItem(qtpie.PieFiling.NULL_CENTER)
428 self._back.insertItem(qtpie.PieFiling.NULL_CENTER)
430 self._entryLayout = QtGui.QHBoxLayout()
431 self._entryLayout.addWidget(self._plus, 0, QtCore.Qt.AlignCenter)
432 self._entryLayout.addWidget(self._entry, 10)
433 self._entryLayout.addWidget(self._back, 0, QtCore.Qt.AlignCenter)
435 self._smsButton = QtGui.QPushButton("SMS")
436 self._smsButton.clicked.connect(self._on_sms_clicked)
437 self._callButton = QtGui.QPushButton("Call")
438 self._callButton.clicked.connect(self._on_call_clicked)
440 self._padLayout = QtGui.QGridLayout()
441 rows = [0, 0, 0, 1, 1, 1, 2, 2, 2]
442 columns = [0, 1, 2] * 3
454 for (num, letters), (row, column) in zip(keys, zip(rows, columns)):
455 self._padLayout.addWidget(
456 self._generate_key_button(num, letters), row, column, QtCore.Qt.AlignCenter
458 self._padLayout.addWidget(self._smsButton, 3, 0)
459 self._padLayout.addWidget(
460 self._generate_key_button("0", ""), 3, 1, QtCore.Qt.AlignCenter
462 self._padLayout.addWidget(self._callButton, 3, 2)
464 self._layout = QtGui.QVBoxLayout()
465 self._layout.addLayout(self._entryLayout)
466 self._layout.addLayout(self._padLayout)
467 self._widget = QtGui.QWidget()
468 self._widget.setLayout(self._layout)
475 self._smsButton.setEnabled(True)
476 self._callButton.setEnabled(True)
479 self._smsButton.setEnabled(False)
480 self._callButton.setEnabled(False)
485 def _generate_key_button(self, center, letters):
486 centerPieItem = self._generate_button_slice(center)
487 button = qtpie.QPieButton(centerPieItem)
488 button.set_center(centerPieItem)
490 if len(letters) == 0:
492 pieItem = qtpie.PieFiling.NULL_CENTER
493 button.insertItem(pieItem)
494 elif len(letters) in [3, 4]:
495 for i in xrange(6 - len(letters)):
496 pieItem = qtpie.PieFiling.NULL_CENTER
497 button.insertItem(pieItem)
499 for letter in letters:
500 pieItem = self._generate_button_slice(letter)
501 button.insertItem(pieItem)
504 pieItem = qtpie.PieFiling.NULL_CENTER
505 button.insertItem(pieItem)
507 raise NotImplementedError("Cannot handle %r" % letters)
510 def _generate_button_slice(self, letter):
511 action = QtGui.QAction(None)
512 action.setText(letter)
513 action.triggered.connect(lambda: self._on_keypress(letter))
514 pieItem = qtpie.QActionPieItem(action)
517 @misc_utils.log_exception(_moduleLogger)
518 def _on_keypress(self, key):
519 self._entry.insert(key)
521 @misc_utils.log_exception(_moduleLogger)
522 def _on_backspace(self, toggled = False):
523 self._entry.backspace()
525 @misc_utils.log_exception(_moduleLogger)
526 def _on_clear_text(self, toggled = False):
529 @misc_utils.log_exception(_moduleLogger)
530 def _on_sms_clicked(self, checked = False):
531 number = str(self._entry.text())
535 @misc_utils.log_exception(_moduleLogger)
536 def _on_call_clicked(self, checked = False):
537 number = str(self._entry.text())
542 class History(object):
550 HISTORY_ITEM_TYPES = ["All", "Received", "Missed", "Placed"]
551 HISTORY_COLUMNS = ["When", "What", "Number", "From"]
552 assert len(HISTORY_COLUMNS) == MAX_IDX
554 def __init__(self, app):
555 self._selectedFilter = self.HISTORY_ITEM_TYPES[0]
558 self._typeSelection = QtGui.QComboBox()
559 self._typeSelection.addItems(self.HISTORY_ITEM_TYPES)
560 self._typeSelection.setCurrentIndex(
561 self.HISTORY_ITEM_TYPES.index(self._selectedFilter)
563 self._typeSelection.currentIndexChanged.connect(self._on_filter_changed)
565 self._itemStore = QtGui.QStandardItemModel()
566 self._itemStore.setHorizontalHeaderLabels(self.HISTORY_COLUMNS)
568 self._itemView = QtGui.QTreeView()
569 self._itemView.setModel(self._itemStore)
570 self._itemView.setUniformRowHeights(True)
571 self._itemView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
572 self._itemView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
573 self._itemView.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
574 self._itemView.setHeaderHidden(True)
575 self._itemView.activated.connect(self._on_row_activated)
577 self._layout = QtGui.QVBoxLayout()
578 self._layout.addWidget(self._typeSelection)
579 self._layout.addWidget(self._itemView)
580 self._widget = QtGui.QWidget()
581 self._widget.setLayout(self._layout)
596 @misc_utils.log_exception(_moduleLogger)
597 def _on_filter_changed(self, newItem):
598 self._selectedFilter = str(newItem)
600 @misc_utils.log_exception(_moduleLogger)
601 def _on_row_activated(self, index):
602 rowIndex = index.row()
605 class Messages(object):
608 VOICEMAIL_MESSAGES = "Voicemail"
609 TEXT_MESSAGES = "SMS"
610 ALL_TYPES = "All Messages"
611 MESSAGE_TYPES = [NO_MESSAGES, VOICEMAIL_MESSAGES, TEXT_MESSAGES, ALL_TYPES]
613 UNREAD_STATUS = "Unread"
614 UNARCHIVED_STATUS = "Inbox"
616 MESSAGE_STATUSES = [UNREAD_STATUS, UNARCHIVED_STATUS, ALL_STATUS]
618 def __init__(self, app):
619 self._selectedTypeFilter = self.ALL_TYPES
620 self._selectedStatusFilter = self.ALL_STATUS
623 self._typeSelection = QtGui.QComboBox()
624 self._typeSelection.addItems(self.MESSAGE_TYPES)
625 self._typeSelection.setCurrentIndex(
626 self.MESSAGE_TYPES.index(self._selectedTypeFilter)
628 self._typeSelection.currentIndexChanged.connect(self._on_type_filter_changed)
630 self._statusSelection = QtGui.QComboBox()
631 self._statusSelection.addItems(self.MESSAGE_STATUSES)
632 self._statusSelection.setCurrentIndex(
633 self.MESSAGE_STATUSES.index(self._selectedStatusFilter)
635 self._statusSelection.currentIndexChanged.connect(self._on_status_filter_changed)
637 self._selectionLayout = QtGui.QHBoxLayout()
638 self._selectionLayout.addWidget(self._typeSelection)
639 self._selectionLayout.addWidget(self._statusSelection)
641 self._itemStore = QtGui.QStandardItemModel()
642 self._itemStore.setHorizontalHeaderLabels(["Messages"])
644 self._itemView = QtGui.QTreeView()
645 self._itemView.setModel(self._itemStore)
646 self._itemView.setUniformRowHeights(True)
647 self._itemView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
648 self._itemView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
649 self._itemView.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
650 self._itemView.setHeaderHidden(True)
651 self._itemView.activated.connect(self._on_row_activated)
653 self._layout = QtGui.QVBoxLayout()
654 self._layout.addLayout(self._selectionLayout)
655 self._layout.addWidget(self._itemView)
656 self._widget = QtGui.QWidget()
657 self._widget.setLayout(self._layout)
672 @misc_utils.log_exception(_moduleLogger)
673 def _on_type_filter_changed(self, newItem):
674 self._selectedTypeFilter = str(newItem)
676 @misc_utils.log_exception(_moduleLogger)
677 def _on_status_filter_changed(self, newItem):
678 self._selectedStatusFilter = str(newItem)
680 @misc_utils.log_exception(_moduleLogger)
681 def _on_row_activated(self, index):
682 rowIndex = index.row()
685 class Contacts(object):
687 def __init__(self, app):
688 self._selectedFilter = ""
691 self._listSelection = QtGui.QComboBox()
692 self._listSelection.addItems([])
693 #self._listSelection.setCurrentIndex(self.HISTORY_ITEM_TYPES.index(self._selectedFilter))
694 self._listSelection.currentIndexChanged.connect(self._on_filter_changed)
696 self._itemStore = QtGui.QStandardItemModel()
697 self._itemStore.setHorizontalHeaderLabels(["Contacts"])
699 self._itemView = QtGui.QTreeView()
700 self._itemView.setModel(self._itemStore)
701 self._itemView.setUniformRowHeights(True)
702 self._itemView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
703 self._itemView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
704 self._itemView.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
705 self._itemView.setHeaderHidden(True)
706 self._itemView.activated.connect(self._on_row_activated)
708 self._layout = QtGui.QVBoxLayout()
709 self._layout.addWidget(self._listSelection)
710 self._layout.addWidget(self._itemView)
711 self._widget = QtGui.QWidget()
712 self._widget.setLayout(self._layout)
727 @misc_utils.log_exception(_moduleLogger)
728 def _on_filter_changed(self, newItem):
729 self._selectedFilter = str(newItem)
731 @misc_utils.log_exception(_moduleLogger)
732 def _on_row_activated(self, index):
733 rowIndex = index.row()
736 class MainWindow(object):
750 assert len(_TAB_TITLES) == MAX_TABS
758 assert len(_TAB_CLASS) == MAX_TABS
760 def __init__(self, parent, app):
761 self._fsContactsPath = os.path.join(constants._data_path_, "contacts")
764 self._errorDisplay = QErrorDisplay()
766 self._tabsContents = [
767 DelayedWidget(self._app)
768 for i in xrange(self.MAX_TABS)
771 self._tabWidget = QtGui.QTabWidget()
772 if maeqt.screen_orientation() == QtCore.Qt.Vertical:
773 self._tabWidget.setTabPosition(QtGui.QTabWidget.South)
775 self._tabWidget.setTabPosition(QtGui.QTabWidget.West)
776 for tabIndex, tabTitle in enumerate(self._TAB_TITLES):
777 self._tabWidget.addTab(self._tabsContents[tabIndex].toplevel, tabTitle)
778 self._tabWidget.currentChanged.connect(self._on_tab_changed)
780 self._layout = QtGui.QVBoxLayout()
781 self._layout.addWidget(self._errorDisplay.toplevel)
782 self._layout.addWidget(self._tabWidget)
784 centralWidget = QtGui.QWidget()
785 centralWidget.setLayout(self._layout)
787 self._window = QtGui.QMainWindow(parent)
788 self._window.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
789 maeqt.set_autorient(self._window, True)
790 maeqt.set_stackable(self._window, True)
791 self._window.setWindowTitle("%s" % constants.__pretty_app_name__)
792 self._window.setCentralWidget(centralWidget)
794 self._loginTabAction = QtGui.QAction(None)
795 self._loginTabAction.setText("Login")
796 self._loginTabAction.triggered.connect(self._on_login)
798 self._importTabAction = QtGui.QAction(None)
799 self._importTabAction.setText("Import")
800 self._importTabAction.triggered.connect(self._on_import)
802 self._refreshTabAction = QtGui.QAction(None)
803 self._refreshTabAction.setText("Refresh")
804 self._refreshTabAction.setShortcut(QtGui.QKeySequence("CTRL+r"))
805 self._refreshTabAction.triggered.connect(self._on_refresh)
807 self._closeWindowAction = QtGui.QAction(None)
808 self._closeWindowAction.setText("Close")
809 self._closeWindowAction.setShortcut(QtGui.QKeySequence("CTRL+w"))
810 self._closeWindowAction.triggered.connect(self._on_close_window)
813 fileMenu = self._window.menuBar().addMenu("&File")
814 fileMenu.addAction(self._loginTabAction)
815 fileMenu.addAction(self._refreshTabAction)
817 toolsMenu = self._window.menuBar().addMenu("&Tools")
818 toolsMenu.addAction(self._importTabAction)
820 self._window.addAction(self._closeWindowAction)
821 self._window.addAction(self._app.quitAction)
822 self._window.addAction(self._app.fullscreenAction)
824 fileMenu = self._window.menuBar().addMenu("&File")
825 fileMenu.addAction(self._loginTabAction)
826 fileMenu.addAction(self._refreshTabAction)
827 fileMenu.addAction(self._closeWindowAction)
828 fileMenu.addAction(self._app.quitAction)
830 viewMenu = self._window.menuBar().addMenu("&View")
831 viewMenu.addAction(self._app.fullscreenAction)
833 toolsMenu = self._window.menuBar().addMenu("&Tools")
834 toolsMenu.addAction(self._importTabAction)
836 self._window.addAction(self._app.logAction)
838 self._initialize_tab(self._tabWidget.currentIndex())
839 self.set_fullscreen(self._app.fullscreenAction.isChecked())
846 def walk_children(self):
851 for child in self.walk_children():
855 for child in self.walk_children():
860 for child in self.walk_children():
861 child.window.destroyed.disconnect(self._on_child_close)
865 def set_fullscreen(self, isFullscreen):
867 self._window.showFullScreen()
869 self._window.showNormal()
870 for child in self.walk_children():
871 child.set_fullscreen(isFullscreen)
873 def _initialize_tab(self, index):
874 assert index < self.MAX_TABS
875 if not self._tabsContents[index].has_child():
876 self._tabsContents[index].set_child(self._TAB_CLASS[index](self._app))
878 @misc_utils.log_exception(_moduleLogger)
879 def _on_login(self, checked = True):
882 @misc_utils.log_exception(_moduleLogger)
883 def _on_tab_changed(self, index):
884 self._initialize_tab(index)
886 @misc_utils.log_exception(_moduleLogger)
887 def _on_refresh(self, checked = True):
888 index = self._tabWidget.currentIndex()
889 self._tabsContents[index].refresh()
891 @misc_utils.log_exception(_moduleLogger)
892 def _on_import(self, checked = True):
893 csvName = QtGui.QFileDialog.getOpenFileName(self._window, caption="Import", filter="CSV Files (*.csv)")
896 shutil.copy2(csvName, self._fsContactsPath)
898 @misc_utils.log_exception(_moduleLogger)
899 def _on_close_window(self, checked = True):
904 app = QtGui.QApplication([])
905 handle = Dialcentral(app)
910 if __name__ == "__main__":
911 logging.basicConfig(level = logging.DEBUG)
913 os.makedirs(constants._data_path_)