1 /*
2  * Stellarium
3  * Copyright (C) 2012 Anton Samoylov
4  * Copyright (C) 2012 Bogdan Marinov
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
19  */
20 
21 #include <QDebug>
22 #include <QKeyEvent>
23 
24 #include "ShortcutLineEdit.hpp"
25 
ShortcutLineEdit(QWidget * parent)26 ShortcutLineEdit::ShortcutLineEdit(QWidget *parent) :
27 	QLineEdit(parent)
28 {
29 	// call clear for setting up private fields
30 	clear();
31 }
32 
getKeySequence() const33 QKeySequence ShortcutLineEdit::getKeySequence() const
34 {
35 	return QKeySequence(keys.value(0, 0), keys.value(1, 0),
36 	                    keys.value(2, 0), keys.value(3, 0));
37 }
38 
isEmpty() const39 bool ShortcutLineEdit::isEmpty() const
40 {
41 	return (keys.isEmpty());
42 }
43 
clear()44 void ShortcutLineEdit::clear()
45 {
46 	keys.clear();
47 	QLineEdit::setText(""); // https://wiki.qt.io/Technical_FAQ#Why_does_the_memory_keep_increasing_when_repeatedly_pasting_text_and_calling_clear.28.29_in_a_QLineEdit.3F
48 	emit contentsChanged();
49 }
50 
backspace()51 void ShortcutLineEdit::backspace()
52 {
53 	if (keys.isEmpty())
54 		return;
55 	keys.removeLast();
56 	setContents(getKeySequence());
57 }
58 
setContents(QKeySequence ks)59 void ShortcutLineEdit::setContents(QKeySequence ks)
60 {
61 	// Avoiding infinite loop of same signal-slot emitting/calling
62 	if (ks.toString(QKeySequence::NativeText) == text())
63 		return;
64 
65 	// Set the keys from the given key sequence
66 	clear();
67 	for (int i = 0; i < ks.count(); ++i)
68 	{
69 		keys.append(ks[i]);
70 	}
71 
72 	// Show Ctrl button as Cmd on Mac
73 	setText(ks.toString(QKeySequence::NativeText));
74 	emit contentsChanged();
75 }
76 
keyPressEvent(QKeyEvent * e)77 void ShortcutLineEdit::keyPressEvent(QKeyEvent *e)
78 {
79 	int nextKey = e->key();
80 	if ( keys.count() > 3 || // too long shortcut
81 	     nextKey == Qt::Key_Control || // don't count modifier keys
82 	     nextKey == Qt::Key_Shift ||
83 	     nextKey == Qt::Key_Meta ||
84 	     nextKey == Qt::Key_Alt )
85 		return;
86 
87 	// applying current modifiers to key
88 	nextKey |= getModifiers(e->modifiers(), e->text());
89 
90 	// If there is selected text, replace *all* instead of appending.
91 	if (hasSelectedText())
92 	{
93 		keys.clear();
94 	}
95 	keys.append(nextKey);
96 
97 	// set displaying information
98 	setText(getKeySequence().toString(QKeySequence::NativeText));
99 	emit contentsChanged();
100 
101 	// not call QLineEdit's event because we already changed contents
102 	e->accept();
103 }
104 
focusInEvent(QFocusEvent * e)105 void ShortcutLineEdit::focusInEvent(QFocusEvent *e)
106 {
107 	// Select the contents so that they are replaced on the next edit
108 	selectAll();
109 	emit focusChanged(false);
110 	QLineEdit::focusInEvent(e);
111 }
112 
focusOutEvent(QFocusEvent * e)113 void ShortcutLineEdit::focusOutEvent(QFocusEvent *e)
114 {
115 	emit focusChanged(true);
116 	QLineEdit::focusOutEvent(e);
117 }
118 
119 
getModifiers(Qt::KeyboardModifiers state,const QString & text)120 int ShortcutLineEdit::getModifiers(Qt::KeyboardModifiers state, const QString &text)
121 {
122 	int result = 0;
123 	// The shift modifier only counts when it is not used to type a symbol
124 	// that is only reachable using the shift key anyway
125 	if ((state & Qt::ShiftModifier) && (text.size() == 0
126 	                                    || !text.at(0).isPrint()
127 	                                    || text.at(0).isLetterOrNumber()
128 	                                    || text.at(0).isSpace()))
129 		result |= Qt::SHIFT;
130 	if (state & Qt::ControlModifier)
131 		result |= Qt::CTRL;
132 	// META key is the same as WIN key on non-MACs
133 	if (state & Qt::MetaModifier)
134 		result |= Qt::META;
135 	if (state & Qt::AltModifier)
136 		result |= Qt::ALT;
137 	return result;
138 }
139