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
23 _moduleLogger = logging.getLogger(__name__)
29 class Dialcentral(object):
32 os.path.dirname(__file__),
33 os.path.join(os.path.dirname(__file__), "../data"),
34 os.path.join(os.path.dirname(__file__), "../lib"),
35 '/usr/share/%s' % constants.__app_name__,
36 '/usr/lib/%s' % constants.__app_name__,
39 def __init__(self, app):
42 self._hiddenCategories = set()
43 self._hiddenUnits = {}
44 self._clipboard = QtGui.QApplication.clipboard()
46 self._mainWindow = None
48 self._fullscreenAction = QtGui.QAction(None)
49 self._fullscreenAction.setText("Fullscreen")
50 self._fullscreenAction.setCheckable(True)
51 self._fullscreenAction.setShortcut(QtGui.QKeySequence("CTRL+Enter"))
52 self._fullscreenAction.toggled.connect(self._on_toggle_fullscreen)
54 self._logAction = QtGui.QAction(None)
55 self._logAction.setText("Log")
56 self._logAction.setShortcut(QtGui.QKeySequence("CTRL+l"))
57 self._logAction.triggered.connect(self._on_log)
59 self._quitAction = QtGui.QAction(None)
60 self._quitAction.setText("Quit")
61 self._quitAction.setShortcut(QtGui.QKeySequence("CTRL+q"))
62 self._quitAction.triggered.connect(self._on_quit)
64 self._app.lastWindowClosed.connect(self._on_app_quit)
67 self._mainWindow = MainWindow(None, self)
68 self._mainWindow.window.destroyed.connect(self._on_child_close)
70 def load_settings(self):
72 with open(constants._user_settings_, "r") as settingsFile:
73 settings = simplejson.load(settingsFile)
75 _moduleLogger.info("No settings")
78 _moduleLogger.info("Settings were corrupt")
81 self._fullscreenAction.setChecked(settings.get("isFullScreen", False))
83 def save_settings(self):
85 "isFullScreen": self._fullscreenAction.isChecked(),
87 with open(constants._user_settings_, "w") as settingsFile:
88 simplejson.dump(settings, settingsFile)
91 def fullscreenAction(self):
92 return self._fullscreenAction
96 return self._logAction
100 return self._quitAction
102 def _close_windows(self):
103 if self._mainWindow is not None:
104 self._mainWindow.window.destroyed.disconnect(self._on_child_close)
105 self._mainWindow.close()
106 self._mainWindow = None
108 @misc_utils.log_exception(_moduleLogger)
109 def _on_app_quit(self, checked = False):
112 @misc_utils.log_exception(_moduleLogger)
113 def _on_child_close(self, obj = None):
114 self._mainWindow = None
116 @misc_utils.log_exception(_moduleLogger)
117 def _on_toggle_fullscreen(self, checked = False):
118 for window in self._walk_children():
119 window.set_fullscreen(checked)
121 @misc_utils.log_exception(_moduleLogger)
122 def _on_log(self, checked = False):
123 with open(constants._user_logpath_, "r") as f:
124 logLines = f.xreadlines()
125 log = "".join(logLines)
126 self._clipboard.setText(log)
128 @misc_utils.log_exception(_moduleLogger)
129 def _on_quit(self, checked = False):
130 self._close_windows()
133 class QErrorDisplay(object):
138 errorIcon = maeqt.get_theme_icon(("dialog-error", "app_install_error", "gtk-dialog-error"))
139 self._severityIcon = errorIcon.pixmap(32, 32)
140 self._severityLabel = QtGui.QLabel()
141 self._severityLabel.setPixmap(self._severityIcon)
143 self._message = QtGui.QLabel()
144 self._message.setText("Boo")
146 closeIcon = maeqt.get_theme_icon(("window-close", "general_close", "gtk-close"))
147 self._closeLabel = QtGui.QPushButton(closeIcon, "")
148 self._closeLabel.clicked.connect(self._on_close)
150 self._controlLayout = QtGui.QHBoxLayout()
151 self._controlLayout.addWidget(self._severityLabel)
152 self._controlLayout.addWidget(self._message)
153 self._controlLayout.addWidget(self._closeLabel)
155 self._topLevelLayout = QtGui.QHBoxLayout()
156 self._topLevelLayout.addLayout(self._controlLayout)
157 self._widget = QtGui.QWidget()
158 self._widget.setLayout(self._topLevelLayout)
165 def push_message(self, message):
166 self._messages.append(message)
167 if 1 == len(self._messages):
168 self._show_message(message)
170 def push_exception(self):
171 userMessage = str(sys.exc_info()[1])
172 _moduleLogger.exception(userMessage)
173 self.push_message(userMessage)
175 def pop_message(self):
176 del self._messages[0]
177 if 0 == len(self._messages):
180 self._message.setText(self._messages[0])
182 def _on_close(self, *args):
185 def _show_message(self, message):
186 self._message.setText(message)
189 def _hide_message(self):
190 self._message.setText("")
194 class CredentialsDialog(object):
197 self._usernameField = QtGui.QLineEdit()
198 self._passwordField = QtGui.QLineEdit()
199 self._passwordField.setEchoMode(QtGui.QLineEdit.PasswordEchoOnEdit)
201 self._credLayout = QtGui.QGridLayout()
202 self._credLayout.addWidget(QtGui.QLabel("Username"), 0, 0)
203 self._credLayout.addWidget(self._usernameField, 0, 1)
204 self._credLayout.addWidget(QtGui.QLabel("Password"), 1, 0)
205 self._credLayout.addWidget(self._passwordField, 1, 1)
207 self._loginButton = QtGui.QPushButton("&Login")
208 self._buttonLayout = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Cancel)
209 self._buttonLayout.addButton(self._loginButton, QtGui.QDialogButtonBox.AcceptRole)
211 self._layout = QtGui.QVBoxLayout()
212 self._layout.addLayout(self._credLayout)
213 self._layout.addLayout(self._buttonLayout)
215 centralWidget = QtGui.QWidget()
216 centralWidget.setLayout(self._layout)
218 self._dialog = QtGui.QDialog()
219 self._dialog.setWindowTitle("Login")
220 self._dialog.setCentralWidget(centralWidget)
221 maeqt.set_autorient(self._dialog, True)
222 self._buttonLayout.accepted.connect(self._dialog.accept)
223 self._buttonLayout.rejected.connect(self._dialog.reject)
225 def run(self, defaultUsername, defaultPassword, parent=None):
226 self._dialog.setParent(parent)
227 self._usernameField.setText(defaultUsername)
228 self._passwordField.setText(defaultPassword)
230 response = self._dialog.exec_()
231 if response == QtGui.QDialog.Accepted:
232 return str(self._usernameField.text()), str(self._passwordField.text())
233 elif response == QtGui.QDialog.Rejected:
234 raise RuntimeError("Login Cancelled")
237 class AccountDialog(object):
240 self._accountNumberLabel = QtGui.QLabel("NUMBER NOT SET")
241 self._clearButton = QtGui.QPushButton("Clear Account")
242 self._clearButton.clicked.connect(self._on_clear)
243 self._doClear = False
245 self._credLayout = QtGui.QGridLayout()
246 self._credLayout.addWidget(QtGui.QLabel("Account"), 0, 0)
247 self._credLayout.addWidget(self._accountNumberLabel, 0, 1)
248 self._credLayout.addWidget(QtGui.QLabel("Callback"), 1, 0)
249 self._credLayout.addWidget(self._clearButton, 2, 1)
251 self._loginButton = QtGui.QPushButton("&Login")
252 self._buttonLayout = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Cancel)
253 self._buttonLayout.addButton(self._loginButton, QtGui.QDialogButtonBox.AcceptRole)
255 self._layout = QtGui.QVBoxLayout()
256 self._layout.addLayout(self._credLayout)
257 self._layout.addLayout(self._buttonLayout)
259 centralWidget = QtGui.QWidget()
260 centralWidget.setLayout(self._layout)
262 self._dialog = QtGui.QDialog()
263 self._dialog.setWindowTitle("Login")
264 self._dialog.setCentralWidget(centralWidget)
265 maeqt.set_autorient(self._dialog, True)
266 self._buttonLayout.accepted.connect(self._dialog.accept)
267 self._buttonLayout.rejected.connect(self._dialog.reject)
273 accountNumber = property(
274 lambda self: str(self._accountNumberLabel.text()),
275 lambda self, num: self._accountNumberLabel.setText(num),
278 def run(self, defaultUsername, defaultPassword, parent=None):
279 self._doClear = False
280 self._dialog.setParent(parent)
281 self._usernameField.setText(defaultUsername)
282 self._passwordField.setText(defaultPassword)
284 response = self._dialog.exec_()
285 if response == QtGui.QDialog.Accepted:
286 return str(self._usernameField.text()), str(self._passwordField.text())
287 elif response == QtGui.QDialog.Rejected:
288 raise RuntimeError("Login Cancelled")
290 def _on_clear(self, checked = False):
292 self._dialog.accept()
295 class SMSEntryWindow(object):
297 def __init__(self, parent, app):
301 self._history = QtGui.QListView()
302 self._smsEntry = QtGui.QTextEdit()
303 self._smsEntry.textChanged.connect(self._on_letter_count_changed)
305 self._entryLayout = QtGui.QVBoxLayout()
306 self._entryLayout.addWidget(self._history)
307 self._entryLayout.addWidget(self._smsEntry)
308 self._entryWidget = QtGui.QWidget()
309 self._entryWidget.setLayout(self._entryLayout)
310 self._scrollEntry = QtGui.QScrollArea()
311 self._scrollEntry.setWidget(self._entryWidget)
312 self._scrollEntry.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignBottom)
313 self._scrollEntry.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
314 self._scrollEntry.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
316 self._characterCountLabel = QtGui.QLabel("Letters: %s" % 0)
317 self._numberSelector = None
318 self._smsButton = QtGui.QPushButton("SMS")
319 self._dialButton = QtGui.QPushButton("Dial")
321 self._buttonLayout = QtGui.QHBoxLayout()
322 self._buttonLayout.addWidget(self._characterCountLabel)
323 self._buttonLayout.addWidget(self._smsButton)
324 self._buttonLayout.addWidget(self._dialButton)
326 self._layout = QtGui.QVBoxLayout()
327 self._layout.addLayout(self._entryLayout)
328 self._layout.addLayout(self._buttonLayout)
330 centralWidget = QtGui.QWidget()
331 centralWidget.setLayout(self._layout)
333 self._window = QtGui.QMainWindow(parent)
334 self._window.setAttribute(QtCore.Qt.WA_DeleteOnClose, False)
335 maeqt.set_autorient(self._window, True)
336 maeqt.set_stackable(self._window, True)
337 self._window.setWindowTitle("Contact")
338 self._window.setCentralWidget(centralWidget)
340 def _update_letter_count(self):
341 count = self._smsEntry.toPlainText().size()
342 self._characterCountLabel.setText("Letters: %s" % count)
344 def _update_button_state(self):
345 if len(self._contacts) == 0:
346 self._dialButton.setEnabled(False)
347 self._smsButton.setEnabled(False)
348 elif len(self._contacts) == 1:
349 count = self._smsEntry.toPlainText().size()
351 self._dialButton.setEnabled(True)
352 self._smsButton.setEnabled(False)
354 self._dialButton.setEnabled(False)
355 self._smsButton.setEnabled(True)
357 self._dialButton.setEnabled(False)
358 self._smsButton.setEnabled(True)
360 def _on_letter_count_changed(self):
361 self._update_letter_count()
362 self._update_button_state()
365 class DelayedWidget(object):
367 def __init__(self, app):
368 self._layout = QtGui.QVBoxLayout()
369 self._widget = QtGui.QWidget()
370 self._widget.setLayout(self._layout)
373 self._isEnabled = True
380 return self._child is not None
382 def set_child(self, child):
383 if self._child is not None:
384 self._layout.removeWidget(self._child.toplevel)
386 if self._child is not None:
387 self._layout.addWidget(self._child.toplevel)
392 self._child.disable()
395 self._isEnabled = True
396 if self._child is not None:
400 self._isEnabled = False
401 if self._child is not None:
402 self._child.disable()
405 if self._child is not None:
409 if self._child is not None:
410 self._child.refresh()
413 class Dialpad(object):
415 def __init__(self, app, session):
417 self._session = session
419 self._plus = self._generate_key_button("+", "")
420 self._entry = QtGui.QLineEdit()
422 backAction = QtGui.QAction(None)
423 backAction.setText("Back")
424 backAction.triggered.connect(self._on_backspace)
425 backPieItem = qtpie.QActionPieItem(backAction)
426 clearAction = QtGui.QAction(None)
427 clearAction.setText("Clear")
428 clearAction.triggered.connect(self._on_clear_text)
429 clearPieItem = qtpie.QActionPieItem(clearAction)
430 self._back = qtpie.QPieButton(backPieItem)
431 self._back.set_center(backPieItem)
432 self._back.insertItem(qtpie.PieFiling.NULL_CENTER)
433 self._back.insertItem(clearPieItem)
434 self._back.insertItem(qtpie.PieFiling.NULL_CENTER)
435 self._back.insertItem(qtpie.PieFiling.NULL_CENTER)
437 self._entryLayout = QtGui.QHBoxLayout()
438 self._entryLayout.addWidget(self._plus, 0, QtCore.Qt.AlignCenter)
439 self._entryLayout.addWidget(self._entry, 10)
440 self._entryLayout.addWidget(self._back, 0, QtCore.Qt.AlignCenter)
442 self._smsButton = QtGui.QPushButton("SMS")
443 self._smsButton.clicked.connect(self._on_sms_clicked)
444 self._callButton = QtGui.QPushButton("Call")
445 self._callButton.clicked.connect(self._on_call_clicked)
447 self._padLayout = QtGui.QGridLayout()
448 rows = [0, 0, 0, 1, 1, 1, 2, 2, 2]
449 columns = [0, 1, 2] * 3
461 for (num, letters), (row, column) in zip(keys, zip(rows, columns)):
462 self._padLayout.addWidget(
463 self._generate_key_button(num, letters), row, column, QtCore.Qt.AlignCenter
465 self._padLayout.addWidget(self._smsButton, 3, 0)
466 self._padLayout.addWidget(
467 self._generate_key_button("0", ""), 3, 1, QtCore.Qt.AlignCenter
469 self._padLayout.addWidget(self._callButton, 3, 2)
471 self._layout = QtGui.QVBoxLayout()
472 self._layout.addLayout(self._entryLayout)
473 self._layout.addLayout(self._padLayout)
474 self._widget = QtGui.QWidget()
475 self._widget.setLayout(self._layout)
482 self._smsButton.setEnabled(True)
483 self._callButton.setEnabled(True)
486 self._smsButton.setEnabled(False)
487 self._callButton.setEnabled(False)
495 def _generate_key_button(self, center, letters):
496 centerPieItem = self._generate_button_slice(center)
497 button = qtpie.QPieButton(centerPieItem)
498 button.set_center(centerPieItem)
500 if len(letters) == 0:
502 pieItem = qtpie.PieFiling.NULL_CENTER
503 button.insertItem(pieItem)
504 elif len(letters) in [3, 4]:
505 for i in xrange(6 - len(letters)):
506 pieItem = qtpie.PieFiling.NULL_CENTER
507 button.insertItem(pieItem)
509 for letter in letters:
510 pieItem = self._generate_button_slice(letter)
511 button.insertItem(pieItem)
514 pieItem = qtpie.PieFiling.NULL_CENTER
515 button.insertItem(pieItem)
517 raise NotImplementedError("Cannot handle %r" % letters)
520 def _generate_button_slice(self, letter):
521 action = QtGui.QAction(None)
522 action.setText(letter)
523 action.triggered.connect(lambda: self._on_keypress(letter))
524 pieItem = qtpie.QActionPieItem(action)
527 @misc_utils.log_exception(_moduleLogger)
528 def _on_keypress(self, key):
529 self._entry.insert(key)
531 @misc_utils.log_exception(_moduleLogger)
532 def _on_backspace(self, toggled = False):
533 self._entry.backspace()
535 @misc_utils.log_exception(_moduleLogger)
536 def _on_clear_text(self, toggled = False):
539 @misc_utils.log_exception(_moduleLogger)
540 def _on_sms_clicked(self, checked = False):
541 number = str(self._entry.text())
543 self._session.draft.add_contact(number, [])
545 @misc_utils.log_exception(_moduleLogger)
546 def _on_call_clicked(self, checked = False):
547 number = str(self._entry.text())
549 self._session.draft.add_contact(number, [])
553 class History(object):
561 HISTORY_ITEM_TYPES = ["All", "Received", "Missed", "Placed"]
562 HISTORY_COLUMNS = ["When", "What", "Number", "From"]
563 assert len(HISTORY_COLUMNS) == MAX_IDX
565 def __init__(self, app, session):
566 self._selectedFilter = self.HISTORY_ITEM_TYPES[0]
568 self._session = session
569 self._session.historyUpdated.connect(self._on_history_updated)
571 self._typeSelection = QtGui.QComboBox()
572 self._typeSelection.addItems(self.HISTORY_ITEM_TYPES)
573 self._typeSelection.setCurrentIndex(
574 self.HISTORY_ITEM_TYPES.index(self._selectedFilter)
576 self._typeSelection.currentIndexChanged.connect(self._on_filter_changed)
578 self._itemStore = QtGui.QStandardItemModel()
579 self._itemStore.setHorizontalHeaderLabels(self.HISTORY_COLUMNS)
581 self._itemView = QtGui.QTreeView()
582 self._itemView.setModel(self._itemStore)
583 self._itemView.setUniformRowHeights(True)
584 self._itemView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
585 self._itemView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
586 self._itemView.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
587 self._itemView.setHeaderHidden(True)
588 self._itemView.activated.connect(self._on_row_activated)
590 self._layout = QtGui.QVBoxLayout()
591 self._layout.addWidget(self._typeSelection)
592 self._layout.addWidget(self._itemView)
593 self._widget = QtGui.QWidget()
594 self._widget.setLayout(self._layout)
596 self._populate_items()
603 self._itemView.setEnabled(True)
606 self._itemView.setEnabled(False)
609 self._itemView.clear()
614 def _populate_items(self):
617 @misc_utils.log_exception(_moduleLogger)
618 def _on_filter_changed(self, newItem):
619 self._selectedFilter = str(newItem)
621 @misc_utils.log_exception(_moduleLogger)
622 def _on_history_updated(self):
623 self._populate_items()
625 @misc_utils.log_exception(_moduleLogger)
626 def _on_row_activated(self, index):
627 rowIndex = index.row()
628 #self._session.draft.add_contact(number, details)
631 class Messages(object):
634 VOICEMAIL_MESSAGES = "Voicemail"
635 TEXT_MESSAGES = "SMS"
636 ALL_TYPES = "All Messages"
637 MESSAGE_TYPES = [NO_MESSAGES, VOICEMAIL_MESSAGES, TEXT_MESSAGES, ALL_TYPES]
639 UNREAD_STATUS = "Unread"
640 UNARCHIVED_STATUS = "Inbox"
642 MESSAGE_STATUSES = [UNREAD_STATUS, UNARCHIVED_STATUS, ALL_STATUS]
644 def __init__(self, app, session):
645 self._selectedTypeFilter = self.ALL_TYPES
646 self._selectedStatusFilter = self.ALL_STATUS
648 self._session = session
649 self._session.messagesUpdated.connect(self._on_messages_updated)
651 self._typeSelection = QtGui.QComboBox()
652 self._typeSelection.addItems(self.MESSAGE_TYPES)
653 self._typeSelection.setCurrentIndex(
654 self.MESSAGE_TYPES.index(self._selectedTypeFilter)
656 self._typeSelection.currentIndexChanged.connect(self._on_type_filter_changed)
658 self._statusSelection = QtGui.QComboBox()
659 self._statusSelection.addItems(self.MESSAGE_STATUSES)
660 self._statusSelection.setCurrentIndex(
661 self.MESSAGE_STATUSES.index(self._selectedStatusFilter)
663 self._statusSelection.currentIndexChanged.connect(self._on_status_filter_changed)
665 self._selectionLayout = QtGui.QHBoxLayout()
666 self._selectionLayout.addWidget(self._typeSelection)
667 self._selectionLayout.addWidget(self._statusSelection)
669 self._itemStore = QtGui.QStandardItemModel()
670 self._itemStore.setHorizontalHeaderLabels(["Messages"])
672 self._itemView = QtGui.QTreeView()
673 self._itemView.setModel(self._itemStore)
674 self._itemView.setUniformRowHeights(True)
675 self._itemView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
676 self._itemView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
677 self._itemView.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
678 self._itemView.setHeaderHidden(True)
679 self._itemView.activated.connect(self._on_row_activated)
681 self._layout = QtGui.QVBoxLayout()
682 self._layout.addLayout(self._selectionLayout)
683 self._layout.addWidget(self._itemView)
684 self._widget = QtGui.QWidget()
685 self._widget.setLayout(self._layout)
687 self._populate_items()
694 self._itemView.setEnabled(True)
697 self._itemView.setEnabled(False)
700 self._itemView.clear()
705 def _populate_items(self):
708 @misc_utils.log_exception(_moduleLogger)
709 def _on_type_filter_changed(self, newItem):
710 self._selectedTypeFilter = str(newItem)
712 @misc_utils.log_exception(_moduleLogger)
713 def _on_status_filter_changed(self, newItem):
714 self._selectedStatusFilter = str(newItem)
716 @misc_utils.log_exception(_moduleLogger)
717 def _on_messages_updated(self):
718 self._populate_items()
720 @misc_utils.log_exception(_moduleLogger)
721 def _on_row_activated(self, index):
722 rowIndex = index.row()
723 #self._session.draft.add_contact(number, details)
726 class Contacts(object):
728 def __init__(self, app, session):
729 self._selectedFilter = ""
731 self._session = session
732 self._session.contactsUpdated.connect(self._on_contacts_updated)
734 self._listSelection = QtGui.QComboBox()
735 self._listSelection.addItems([])
736 #self._listSelection.setCurrentIndex(self.HISTORY_ITEM_TYPES.index(self._selectedFilter))
737 self._listSelection.currentIndexChanged.connect(self._on_filter_changed)
739 self._itemStore = QtGui.QStandardItemModel()
740 self._itemStore.setHorizontalHeaderLabels(["Contacts"])
742 self._itemView = QtGui.QTreeView()
743 self._itemView.setModel(self._itemStore)
744 self._itemView.setUniformRowHeights(True)
745 self._itemView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
746 self._itemView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
747 self._itemView.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
748 self._itemView.setHeaderHidden(True)
749 self._itemView.activated.connect(self._on_row_activated)
751 self._layout = QtGui.QVBoxLayout()
752 self._layout.addWidget(self._listSelection)
753 self._layout.addWidget(self._itemView)
754 self._widget = QtGui.QWidget()
755 self._widget.setLayout(self._layout)
757 self._populate_items()
764 self._itemView.setEnabled(True)
767 self._itemView.setEnabled(False)
770 self._itemView.clear()
775 def _populate_items(self):
778 @misc_utils.log_exception(_moduleLogger)
779 def _on_filter_changed(self, newItem):
780 self._selectedFilter = str(newItem)
782 @misc_utils.log_exception(_moduleLogger)
783 def _on_contacts_updated(self):
784 self._populate_items()
786 @misc_utils.log_exception(_moduleLogger)
787 def _on_row_activated(self, index):
788 rowIndex = index.row()
789 #self._session.draft.add_contact(number, details)
792 class MainWindow(object):
806 assert len(_TAB_TITLES) == MAX_TABS
814 assert len(_TAB_CLASS) == MAX_TABS
816 def __init__(self, parent, app):
817 self._fsContactsPath = os.path.join(constants._data_path_, "contacts")
819 self._session = session.Session()
821 self._errorDisplay = QErrorDisplay()
823 self._tabsContents = [
824 DelayedWidget(self._app)
825 for i in xrange(self.MAX_TABS)
827 for tab in self._tabsContents:
830 self._tabWidget = QtGui.QTabWidget()
831 if maeqt.screen_orientation() == QtCore.Qt.Vertical:
832 self._tabWidget.setTabPosition(QtGui.QTabWidget.South)
834 self._tabWidget.setTabPosition(QtGui.QTabWidget.West)
835 for tabIndex, tabTitle in enumerate(self._TAB_TITLES):
836 self._tabWidget.addTab(self._tabsContents[tabIndex].toplevel, tabTitle)
837 self._tabWidget.currentChanged.connect(self._on_tab_changed)
839 self._layout = QtGui.QVBoxLayout()
840 self._layout.addWidget(self._errorDisplay.toplevel)
841 self._layout.addWidget(self._tabWidget)
843 centralWidget = QtGui.QWidget()
844 centralWidget.setLayout(self._layout)
846 self._window = QtGui.QMainWindow(parent)
847 self._window.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
848 maeqt.set_autorient(self._window, True)
849 maeqt.set_stackable(self._window, True)
850 self._window.setWindowTitle("%s" % constants.__pretty_app_name__)
851 self._window.setCentralWidget(centralWidget)
853 self._loginTabAction = QtGui.QAction(None)
854 self._loginTabAction.setText("Login")
855 self._loginTabAction.triggered.connect(self._on_login)
857 self._importTabAction = QtGui.QAction(None)
858 self._importTabAction.setText("Import")
859 self._importTabAction.triggered.connect(self._on_import)
861 self._refreshTabAction = QtGui.QAction(None)
862 self._refreshTabAction.setText("Refresh")
863 self._refreshTabAction.setShortcut(QtGui.QKeySequence("CTRL+r"))
864 self._refreshTabAction.triggered.connect(self._on_refresh)
866 self._closeWindowAction = QtGui.QAction(None)
867 self._closeWindowAction.setText("Close")
868 self._closeWindowAction.setShortcut(QtGui.QKeySequence("CTRL+w"))
869 self._closeWindowAction.triggered.connect(self._on_close_window)
872 fileMenu = self._window.menuBar().addMenu("&File")
873 fileMenu.addAction(self._loginTabAction)
874 fileMenu.addAction(self._refreshTabAction)
876 toolsMenu = self._window.menuBar().addMenu("&Tools")
877 toolsMenu.addAction(self._importTabAction)
879 self._window.addAction(self._closeWindowAction)
880 self._window.addAction(self._app.quitAction)
881 self._window.addAction(self._app.fullscreenAction)
883 fileMenu = self._window.menuBar().addMenu("&File")
884 fileMenu.addAction(self._loginTabAction)
885 fileMenu.addAction(self._refreshTabAction)
886 fileMenu.addAction(self._closeWindowAction)
887 fileMenu.addAction(self._app.quitAction)
889 viewMenu = self._window.menuBar().addMenu("&View")
890 viewMenu.addAction(self._app.fullscreenAction)
892 toolsMenu = self._window.menuBar().addMenu("&Tools")
893 toolsMenu.addAction(self._importTabAction)
895 self._window.addAction(self._app.logAction)
897 self._initialize_tab(self._tabWidget.currentIndex())
898 self.set_fullscreen(self._app.fullscreenAction.isChecked())
905 def walk_children(self):
910 for child in self.walk_children():
914 for child in self.walk_children():
919 for child in self.walk_children():
920 child.window.destroyed.disconnect(self._on_child_close)
924 def set_fullscreen(self, isFullscreen):
926 self._window.showFullScreen()
928 self._window.showNormal()
929 for child in self.walk_children():
930 child.set_fullscreen(isFullscreen)
932 def _initialize_tab(self, index):
933 assert index < self.MAX_TABS
934 if not self._tabsContents[index].has_child():
935 self._tabsContents[index].set_child(
936 self._TAB_CLASS[index](self._app, self._session)
939 @misc_utils.log_exception(_moduleLogger)
940 def _on_login(self, checked = True):
943 @misc_utils.log_exception(_moduleLogger)
944 def _on_tab_changed(self, index):
945 self._initialize_tab(index)
947 @misc_utils.log_exception(_moduleLogger)
948 def _on_refresh(self, checked = True):
949 index = self._tabWidget.currentIndex()
950 self._tabsContents[index].refresh()
952 @misc_utils.log_exception(_moduleLogger)
953 def _on_import(self, checked = True):
954 csvName = QtGui.QFileDialog.getOpenFileName(self._window, caption="Import", filter="CSV Files (*.csv)")
957 shutil.copy2(csvName, self._fsContactsPath)
959 @misc_utils.log_exception(_moduleLogger)
960 def _on_close_window(self, checked = True):
965 app = QtGui.QApplication([])
966 handle = Dialcentral(app)
971 if __name__ == "__main__":
972 logging.basicConfig(level = logging.DEBUG)
974 os.makedirs(constants._data_path_)