├── .gitignore
├── .travis.yml
├── CMakeLists.txt
├── Info.plist.in
├── LICENSE.txt
├── Qocoa.pro
├── README.md
├── TODO.md
├── gallery.cpp
├── gallery.h
├── gallery.png
├── main.cpp
├── qbutton.h
├── qbutton_mac.mm
├── qbutton_nonmac.cpp
├── qocoa_mac.h
├── qprogressindicatorspinning.h
├── qprogressindicatorspinning_mac.mm
├── qprogressindicatorspinning_nonmac.cpp
├── qprogressindicatorspinning_nonmac.gif
├── qprogressindicatorspinning_nonmac.qrc
├── qsearchfield.h
├── qsearchfield_mac.mm
├── qsearchfield_nonmac.cpp
├── qsearchfield_nonmac.qrc
├── qsearchfield_nonmac_clear.png
├── qsearchfield_nonmac_magnifier.png
└── qsearchfield_nonmac_magnifier_menu.png
/.gitignore:
--------------------------------------------------------------------------------
1 | cmake/
2 | qmake/
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | os: osx
3 | compiler: clang
4 | env:
5 | - XMAKE=qmake
6 | matrix:
7 | include:
8 | - compiler: clang
9 | env:
10 | - XMAKE=cmake
11 | - XMAKE_OPTIONS="."
12 | - compiler: clang
13 | env:
14 | - XMAKE=qmake
15 | - XMAKE_OPTIONS="NON_MAC_WIDGETS=1"
16 | - compiler: gcc
17 | env:
18 | - XMAKE=cmake
19 | - XMAKE_OPTIONS=". -DNON_MAC_WIDGETS=ON"
20 | - CC=gcc-4.9
21 | - CXX=g++-4.9
22 | before_install:
23 | - brew update
24 | install:
25 | - brew install qt
26 | script:
27 | - $XMAKE $XMAKE_OPTIONS && make
28 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | project(Qocoa)
2 | cmake_minimum_required(VERSION 2.8)
3 |
4 | option(NON_MAC_WIDGETS "Force non-Mac widgets on OS X (useful for testing)" OFF)
5 |
6 | find_package(Qt4 COMPONENTS QtMain QtCore QtGui REQUIRED)
7 | include(UseQt4)
8 |
9 | set(SOURCES
10 | main.cpp
11 | gallery.cpp
12 | )
13 |
14 | set(HEADERS
15 | gallery.h
16 | qsearchfield.h
17 | qbutton.h
18 | qprogressindicatorspinning.h
19 | )
20 |
21 | qt4_wrap_cpp(MOC_SOURCES ${HEADERS})
22 |
23 | if(APPLE AND NOT ${NON_MAC_WIDGETS})
24 | list(APPEND SOURCES
25 | qsearchfield_mac.mm
26 | qbutton_mac.mm
27 | qprogressindicatorspinning_mac.mm
28 | )
29 | else()
30 | message(here)
31 | list(APPEND SOURCES
32 | qsearchfield_nonmac.cpp
33 | qbutton_nonmac.cpp
34 | qprogressindicatorspinning_nonmac.cpp
35 | )
36 | set(RESOURCES
37 | qsearchfield_nonmac.qrc
38 | qprogressindicatorspinning_nonmac.qrc
39 | )
40 | qt4_add_resources(RESOURCES_SOURCES ${RESOURCES})
41 | endif()
42 |
43 | add_executable(Qocoa
44 | WIN32 MACOSX_BUNDLE
45 | ${SOURCES} ${MOC_SOURCES} ${RESOURCES_SOURCES}
46 | )
47 | target_link_libraries(Qocoa ${QT_LIBRARIES})
48 |
49 | if(APPLE AND NOT ${NON_MAC_WIDGETS})
50 | set_target_properties(Qocoa PROPERTIES LINK_FLAGS "-framework Foundation -framework AppKit")
51 | set_target_properties(Qocoa PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in)
52 | endif()
53 |
--------------------------------------------------------------------------------
/Info.plist.in:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 | NSPrincipalClass
10 | NSApplication
11 | CFBundleDevelopmentRegion
12 | English
13 | CFBundleExecutable
14 | ${MACOSX_BUNDLE_EXECUTABLE_NAME}
15 | CFBundleGetInfoString
16 | ${MACOSX_BUNDLE_INFO_STRING}
17 | CFBundleIconFile
18 | ${MACOSX_BUNDLE_ICON_FILE}
19 | CFBundleIdentifier
20 | ${MACOSX_BUNDLE_GUI_IDENTIFIER}
21 | CFBundleInfoDictionaryVersion
22 | 6.0
23 | CFBundleLongVersionString
24 | ${MACOSX_BUNDLE_LONG_VERSION_STRING}
25 | CFBundleName
26 | ${MACOSX_BUNDLE_BUNDLE_NAME}
27 | CFBundlePackageType
28 | APPL
29 | CFBundleShortVersionString
30 | ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
31 | CFBundleSignature
32 | ????
33 | CFBundleVersion
34 | ${MACOSX_BUNDLE_BUNDLE_VERSION}
35 | CSResourcesFileMapped
36 |
37 | LSRequiresCarbon
38 |
39 | NSHumanReadableCopyright
40 | ${MACOSX_BUNDLE_COPYRIGHT}
41 |
42 |
43 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (C) 2011 by Mike McQuaid
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Qocoa.pro:
--------------------------------------------------------------------------------
1 | SOURCES += main.cpp\
2 | gallery.cpp \
3 |
4 | HEADERS += gallery.h \
5 | qocoa_mac.h \
6 | qsearchfield.h \
7 | qbutton.h \
8 | qprogressindicatorspinning.h \
9 |
10 | !mac|equals(NON_MAC_WIDGETS, 1) { {
11 | SOURCES += qsearchfield_nonmac.cpp qbutton_nonmac.cpp qprogressindicatorspinning_nonmac.cpp
12 | RESOURCES += qsearchfield_nonmac.qrc qprogressindicatorspinning_nonmac.qrc
13 | } else {
14 | OBJECTIVE_SOURCES += qsearchfield_mac.mm qbutton_mac.mm qprogressindicatorspinning_mac.mm
15 | LIBS += -framework Foundation -framework Appkit
16 | QMAKE_CFLAGS += -mmacosx-version-min=10.6
17 | }
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Qocoa
2 | Qocoa is a collection of Qt wrappers for OSX's Cocoa widgets.
3 |
4 | ## Features
5 | - basic fallback to sensible Qt types on non-OSX platforms
6 | - shared class headers which expose no implementation details
7 | - typical Qt signal/slot-based API
8 | - trivial to import into projects (class header/implementation, [single shared global header](https://github.com/mikemcquaid/Qocoa/blob/master/qocoa_mac.h))
9 |
10 | ## Building
11 | ```
12 | git clone git://github.com/mikemcquaid/Qocoa.git
13 | cd Qocoa
14 | qmake # or cmake .
15 | make
16 | ```
17 |
18 | ## Status
19 | I'm not personally working on this any more but will accept pull-requests.
20 |
21 | [](https://travis-ci.org/MikeMcQuaid/Qocoa)
22 |
23 | ## Usage
24 | For each class you want to use copy the [`qocoa_mac.h`](https://github.com/mikemcquaid/Qocoa/blob/master/qocoa_mac.h), `$CLASS.h`, `$CLASS_mac.*` and `$CLASS_nonmac.*` files into your source tree and add them to your buildsystem. Examples are provided for [CMake](https://github.com/mikemcquaid/Qocoa/blob/master/CMakeLists.txt) and [QMake](https://github.com/mikemcquaid/Qocoa/blob/master/Qocoa.pro).
25 |
26 | ## Contact
27 | [Mike McQuaid](mailto:mike@mikemcquaid.com)
28 |
29 | ## License
30 | Qocoa is licensed under the [MIT License](http://en.wikipedia.org/wiki/MIT_License).
31 | The full license text is available in [LICENSE.txt](https://github.com/mikemcquaid/Qocoa/blob/master/LICENSE.txt).
32 |
33 | Magnifier and EditClear icons taken from [QtCreator](http://qt-project.org/) and are licensed under the [LGPL](http://www.gnu.org/copyleft/lesser.html).
34 |
35 | Other icons are taken from the [Oxygen Project](http://www.oxygen-icons.org/) and are licensed under the [Creative Commons Attribution-ShareAlike 3.0 License](http://creativecommons.org/licenses/by-sa/3.0/).
36 |
37 | ## Gallery
38 | 
39 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | Widgets I hope to implement (or at least investigate):
2 |
3 | - NSTokenField
4 | - NSSegmentedControl
5 | - NSLevelIndicator
6 | - NSPathControl
7 | - NSSlider (Circular)
8 | - NSSplitView
9 | - NSTextFinder
10 | - NSOutlineView in an NSScrollView (Source List)
11 | - NSDrawer
12 | - PDFView
13 | - WebView
14 |
--------------------------------------------------------------------------------
/gallery.cpp:
--------------------------------------------------------------------------------
1 | #include "gallery.h"
2 |
3 | #include
4 |
5 | #include "qsearchfield.h"
6 | #include "qbutton.h"
7 | #include "qprogressindicatorspinning.h"
8 |
9 | Gallery::Gallery(QWidget *parent) : QWidget(parent)
10 | {
11 | setWindowTitle("Qocoa Gallery");
12 | QVBoxLayout *layout = new QVBoxLayout(this);
13 |
14 | QSearchField *searchField = new QSearchField(this);
15 | layout->addWidget(searchField);
16 |
17 | QSearchField *searchFieldPlaceholder = new QSearchField(this);
18 | searchFieldPlaceholder->setPlaceholderText("Placeholder text");
19 | layout->addWidget(searchFieldPlaceholder);
20 |
21 | QButton *roundedButton = new QButton(this, QButton::Rounded);
22 | roundedButton->setText("Button");
23 | layout->addWidget(roundedButton);
24 |
25 | QButton *regularSquareButton = new QButton(this, QButton::RegularSquare);
26 | regularSquareButton->setText("Button");
27 | layout->addWidget(regularSquareButton);
28 |
29 | QButton *disclosureButton = new QButton(this, QButton::Disclosure);
30 | layout->addWidget(disclosureButton);
31 |
32 | QButton *shadowlessSquareButton = new QButton(this, QButton::ShadowlessSquare);
33 | shadowlessSquareButton->setText("Button");
34 | layout->addWidget(shadowlessSquareButton);
35 |
36 | QButton *circularButton = new QButton(this, QButton::Circular);
37 | layout->addWidget(circularButton);
38 |
39 | QButton *textureSquareButton = new QButton(this, QButton::TexturedSquare);
40 | textureSquareButton->setText("Textured Button");
41 | layout->addWidget(textureSquareButton);
42 |
43 | QButton *helpButton = new QButton(this, QButton::HelpButton);
44 | layout->addWidget(helpButton);
45 |
46 | QButton *smallSquareButton = new QButton(this, QButton::SmallSquare);
47 | smallSquareButton->setText("Gradient Button");
48 | layout->addWidget(smallSquareButton);
49 |
50 | QButton *texturedRoundedButton = new QButton(this, QButton::TexturedRounded);
51 | texturedRoundedButton->setText("Round Textured");
52 | layout->addWidget(texturedRoundedButton);
53 |
54 | QButton *roundedRectangleButton = new QButton(this, QButton::RoundRect);
55 | roundedRectangleButton->setText("Rounded Rect Button");
56 | layout->addWidget(roundedRectangleButton);
57 |
58 | QButton *recessedButton = new QButton(this, QButton::Recessed);
59 | recessedButton->setText("Recessed Button");
60 | layout->addWidget(recessedButton);
61 |
62 | QButton *roundedDisclosureButton = new QButton(this, QButton::RoundedDisclosure);
63 | layout->addWidget(roundedDisclosureButton);
64 |
65 | #ifdef __MAC_10_7
66 | QButton *inlineButton = new QButton(this, QButton::Inline);
67 | inlineButton->setText("Inline Button");
68 | layout->addWidget(inlineButton);
69 | #endif
70 |
71 |
72 | QProgressIndicatorSpinning *progressIndicatorSpinning = new QProgressIndicatorSpinning(this);
73 | progressIndicatorSpinning->animate();
74 | layout->addWidget(progressIndicatorSpinning);
75 | }
76 |
--------------------------------------------------------------------------------
/gallery.h:
--------------------------------------------------------------------------------
1 | #ifndef GALLERY_H
2 | #define GALLERY_H
3 |
4 | #include
5 |
6 | class Gallery : public QWidget
7 | {
8 | Q_OBJECT
9 |
10 | public:
11 | explicit Gallery(QWidget *parent = 0);
12 | };
13 |
14 | #endif // WIDGET_H
15 |
--------------------------------------------------------------------------------
/gallery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MikeMcQuaid/Qocoa/3a5623cb916e540ee46f5c13a85236ff458f4aba/gallery.png
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "gallery.h"
4 |
5 | int main(int argc, char *argv[])
6 | {
7 | QApplication application(argc, argv);
8 |
9 | Gallery gallery;
10 | gallery.show();
11 |
12 | return application.exec();
13 | }
14 |
--------------------------------------------------------------------------------
/qbutton.h:
--------------------------------------------------------------------------------
1 | #ifndef QBUTTON_H
2 | #define QBUTTON_H
3 |
4 | #include
5 | #include
6 |
7 | class QButtonPrivate;
8 | class QButton : public QWidget
9 | {
10 | Q_OBJECT
11 | public:
12 | // Matches NSBezelStyle
13 | enum BezelStyle {
14 | Rounded = 1,
15 | RegularSquare = 2,
16 | Disclosure = 5,
17 | ShadowlessSquare = 6,
18 | Circular = 7,
19 | TexturedSquare = 8,
20 | HelpButton = 9,
21 | SmallSquare = 10,
22 | TexturedRounded = 11,
23 | RoundRect = 12,
24 | Recessed = 13,
25 | RoundedDisclosure = 14,
26 | #ifdef __MAC_10_7
27 | Inline = 15
28 | #endif
29 | };
30 |
31 | explicit QButton(QWidget *parent, BezelStyle bezelStyle = Rounded);
32 |
33 | public slots:
34 | void setText(const QString &text);
35 | void setImage(const QPixmap &image);
36 | void setChecked(bool checked);
37 |
38 | public:
39 | void setCheckable(bool checkable);
40 | bool isChecked();
41 |
42 | signals:
43 | void clicked(bool checked = false);
44 |
45 | private:
46 | friend class QButtonPrivate;
47 | QPointer pimpl;
48 | };
49 | #endif // QBUTTON_H
50 |
--------------------------------------------------------------------------------
/qbutton_mac.mm:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2011 by Mike McQuaid
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | #include "qbutton.h"
24 |
25 | #include "qocoa_mac.h"
26 |
27 | #import "Foundation/NSAutoreleasePool.h"
28 | #import "AppKit/NSButton.h"
29 | #import "AppKit/NSFont.h"
30 |
31 | class QButtonPrivate : public QObject
32 | {
33 | public:
34 | QButtonPrivate(QButton *qButton, NSButton *nsButton, QButton::BezelStyle bezelStyle)
35 | : QObject(qButton), qButton(qButton), nsButton(nsButton)
36 | {
37 | switch(bezelStyle) {
38 | case QButton::Disclosure:
39 | case QButton::Circular:
40 | #ifdef __MAC_10_7
41 | case QButton::Inline:
42 | #endif
43 | case QButton::RoundedDisclosure:
44 | case QButton::HelpButton:
45 | [nsButton setTitle:@""];
46 | default:
47 | break;
48 | }
49 |
50 | NSFont* font = 0;
51 | switch(bezelStyle) {
52 | case QButton::RoundRect:
53 | font = [NSFont fontWithName:@"Lucida Grande" size:12];
54 | break;
55 |
56 | case QButton::Recessed:
57 | font = [NSFont fontWithName:@"Lucida Grande Bold" size:12];
58 | break;
59 |
60 | #ifdef __MAC_10_7
61 | case QButton::Inline:
62 | font = [NSFont boldSystemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
63 | break;
64 | #endif
65 |
66 | default:
67 | font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
68 | break;
69 | }
70 | [nsButton setFont:font];
71 |
72 | switch(bezelStyle) {
73 | case QButton::Rounded:
74 | qButton->setMinimumWidth(40);
75 | qButton->setFixedHeight(24);
76 | qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
77 | break;
78 | case QButton::RegularSquare:
79 | case QButton::TexturedSquare:
80 | qButton->setMinimumSize(14, 23);
81 | qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
82 | break;
83 | case QButton::ShadowlessSquare:
84 | qButton->setMinimumSize(5, 25);
85 | qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
86 | break;
87 | case QButton::SmallSquare:
88 | qButton->setMinimumSize(4, 21);
89 | qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
90 | break;
91 | case QButton::TexturedRounded:
92 | qButton->setMinimumSize(10, 22);
93 | qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
94 | break;
95 | case QButton::RoundRect:
96 | case QButton::Recessed:
97 | qButton->setMinimumWidth(16);
98 | qButton->setFixedHeight(18);
99 | qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
100 | break;
101 | case QButton::Disclosure:
102 | qButton->setMinimumWidth(13);
103 | qButton->setFixedHeight(13);
104 | qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
105 | break;
106 | case QButton::Circular:
107 | qButton->setMinimumSize(16, 16);
108 | qButton->setMaximumHeight(40);
109 | qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
110 | break;
111 | case QButton::HelpButton:
112 | case QButton::RoundedDisclosure:
113 | qButton->setMinimumWidth(22);
114 | qButton->setFixedHeight(22);
115 | qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
116 | break;
117 | #ifdef __MAC_10_7
118 | case QButton::Inline:
119 | qButton->setMinimumWidth(10);
120 | qButton->setFixedHeight(16);
121 | qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
122 | break;
123 | #endif
124 | }
125 |
126 | switch(bezelStyle) {
127 | case QButton::Recessed:
128 | [nsButton setButtonType:NSPushOnPushOffButton];
129 | case QButton::Disclosure:
130 | [nsButton setButtonType:NSOnOffButton];
131 | default:
132 | [nsButton setButtonType:NSMomentaryPushInButton];
133 | }
134 |
135 | [nsButton setBezelStyle:bezelStyle];
136 | }
137 |
138 | void clicked()
139 | {
140 | emit qButton->clicked(qButton->isChecked());
141 | }
142 |
143 | ~QButtonPrivate() {
144 | [[nsButton target] release];
145 | [nsButton setTarget:nil];
146 | }
147 |
148 | QButton *qButton;
149 | NSButton *nsButton;
150 | };
151 |
152 | @interface QButtonTarget : NSObject
153 | {
154 | @public
155 | QPointer pimpl;
156 | }
157 | -(void)clicked;
158 | @end
159 |
160 | @implementation QButtonTarget
161 | -(void)clicked {
162 | Q_ASSERT(pimpl);
163 | if (pimpl)
164 | pimpl->clicked();
165 | }
166 | @end
167 |
168 | QButton::QButton(QWidget *parent, BezelStyle bezelStyle) : QWidget(parent)
169 | {
170 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
171 |
172 | NSButton *button = [[NSButton alloc] init];
173 | pimpl = new QButtonPrivate(this, button, bezelStyle);
174 |
175 | QButtonTarget *target = [[QButtonTarget alloc] init];
176 | target->pimpl = pimpl;
177 | [button setTarget:target];
178 |
179 | [button setAction:@selector(clicked)];
180 |
181 | setupLayout(button, this);
182 |
183 | [button release];
184 |
185 | [pool drain];
186 | }
187 |
188 | void QButton::setText(const QString &text)
189 | {
190 | Q_ASSERT(pimpl);
191 | if (!pimpl)
192 | return;
193 |
194 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
195 | [pimpl->nsButton setTitle:fromQString(text)];
196 | [pool drain];
197 | }
198 |
199 | void QButton::setImage(const QPixmap &image)
200 | {
201 | Q_ASSERT(pimpl);
202 | if (pimpl)
203 | [pimpl->nsButton setImage:fromQPixmap(image)];
204 | }
205 |
206 | void QButton::setChecked(bool checked)
207 | {
208 | Q_ASSERT(pimpl);
209 | if (pimpl)
210 | [pimpl->nsButton setState:checked];
211 | }
212 |
213 | void QButton::setCheckable(bool checkable)
214 | {
215 | const NSInteger cellMask = checkable ? NSChangeBackgroundCellMask : NSNoCellMask;
216 |
217 | Q_ASSERT(pimpl);
218 | if (pimpl)
219 | [[pimpl->nsButton cell] setShowsStateBy:cellMask];
220 | }
221 |
222 | bool QButton::isChecked()
223 | {
224 | Q_ASSERT(pimpl);
225 | if (!pimpl)
226 | return false;
227 |
228 | return [pimpl->nsButton state];
229 | }
230 |
--------------------------------------------------------------------------------
/qbutton_nonmac.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2011 by Mike McQuaid
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | #include "qbutton.h"
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | class QButtonPrivate : public QObject
31 | {
32 | public:
33 | QButtonPrivate(QButton *button, QAbstractButton *abstractButton)
34 | : QObject(button), abstractButton(abstractButton) {}
35 | QPointer abstractButton;
36 | };
37 |
38 | QButton::QButton(QWidget *parent, BezelStyle) : QWidget(parent)
39 | {
40 | QAbstractButton *button = 0;
41 | if (qobject_cast(parent))
42 | button = new QToolButton(this);
43 | else
44 | button = new QPushButton(this);
45 | connect(button, SIGNAL(clicked()),
46 | this, SIGNAL(clicked()));
47 | pimpl = new QButtonPrivate(this, button);
48 |
49 | QVBoxLayout *layout = new QVBoxLayout(this);
50 | layout->setMargin(0);
51 | layout->addWidget(button);
52 | }
53 |
54 | void QButton::setText(const QString &text)
55 | {
56 | Q_ASSERT(pimpl);
57 | if (pimpl)
58 | pimpl->abstractButton->setText(text);
59 | }
60 |
61 | void QButton::setImage(const QPixmap &image)
62 | {
63 | Q_ASSERT(pimpl);
64 | if (pimpl)
65 | pimpl->abstractButton->setIcon(image);
66 | }
67 |
68 | void QButton::setChecked(bool checked)
69 | {
70 | Q_ASSERT(pimpl);
71 | if (pimpl)
72 | pimpl->abstractButton->setChecked(checked);
73 | }
74 |
75 | void QButton::setCheckable(bool checkable)
76 | {
77 | Q_ASSERT(pimpl);
78 | if (pimpl)
79 | pimpl->abstractButton->setCheckable(checkable);
80 | }
81 |
82 | bool QButton::isChecked()
83 | {
84 | Q_ASSERT(pimpl);
85 | if (!pimpl)
86 | return false;
87 |
88 | return pimpl->abstractButton->isChecked();
89 | }
90 |
--------------------------------------------------------------------------------
/qocoa_mac.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2011 by Mike McQuaid
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
30 | #include
31 | #endif
32 |
33 | static inline NSString* fromQString(const QString &string)
34 | {
35 | const QByteArray utf8 = string.toUtf8();
36 | const char* cString = utf8.constData();
37 | return [[NSString alloc] initWithUTF8String:cString];
38 | }
39 |
40 | static inline QString toQString(NSString *string)
41 | {
42 | if (!string)
43 | return QString();
44 | return QString::fromUtf8([string UTF8String]);
45 | }
46 |
47 | static inline NSImage* fromQPixmap(const QPixmap &pixmap)
48 | {
49 | #if QT_VERSION < QT_VERSION_CHECK(5,0,0)
50 | CGImageRef cgImage = pixmap.toMacCGImageRef();
51 | #else
52 | CGImageRef cgImage = QtMac::toCGImageRef(pixmap);
53 | #endif
54 | return [[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize];
55 | }
56 |
57 | static inline void setupLayout(NSView *cocoaView, QWidget *parent)
58 | {
59 | parent->setAttribute(Qt::WA_NativeWindow);
60 | QVBoxLayout *layout = new QVBoxLayout(parent);
61 | layout->setMargin(0);
62 | layout->addWidget(new QMacCocoaViewContainer(cocoaView, parent));
63 | }
64 |
--------------------------------------------------------------------------------
/qprogressindicatorspinning.h:
--------------------------------------------------------------------------------
1 | #ifndef QPROGRESSINDICATORSPINNING_H
2 | #define QPROGRESSINDICATORSPINNING_H
3 |
4 | #include
5 | #include
6 |
7 | class QProgressIndicatorSpinningPrivate;
8 | class QProgressIndicatorSpinning : public QWidget
9 | {
10 | Q_OBJECT
11 | public:
12 | // Matches NSProgressIndicatorThickness
13 | enum Thickness {
14 | Default = 14,
15 | Small = 10,
16 | Large = 18,
17 | Aqua = 12
18 | };
19 |
20 | explicit QProgressIndicatorSpinning(QWidget *parent,
21 | Thickness thickness = Default);
22 | public slots:
23 | void animate(bool animate = true);
24 | private:
25 | friend class QProgressIndicatorSpinningPrivate;
26 | QPointer pimpl;
27 | };
28 |
29 | #endif // QPROGRESSINDICATORSPINNING_H
30 |
--------------------------------------------------------------------------------
/qprogressindicatorspinning_mac.mm:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2011 by Mike McQuaid
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | #include "qprogressindicatorspinning.h"
24 |
25 | #include "qocoa_mac.h"
26 |
27 | #import "Foundation/NSAutoreleasePool.h"
28 | #import "AppKit/NSProgressIndicator.h"
29 |
30 | class QProgressIndicatorSpinningPrivate : public QObject
31 | {
32 | public:
33 | QProgressIndicatorSpinningPrivate(QProgressIndicatorSpinning *qProgressIndicatorSpinning,
34 | NSProgressIndicator *nsProgressIndicator)
35 | : QObject(qProgressIndicatorSpinning), nsProgressIndicator(nsProgressIndicator) {}
36 |
37 | NSProgressIndicator *nsProgressIndicator;
38 | };
39 |
40 | QProgressIndicatorSpinning::QProgressIndicatorSpinning(QWidget *parent,
41 | Thickness thickness)
42 | : QWidget(parent)
43 | {
44 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
45 |
46 | NSProgressIndicator *progress = [[NSProgressIndicator alloc] init];
47 | [progress setStyle:NSProgressIndicatorSpinningStyle];
48 |
49 | pimpl = new QProgressIndicatorSpinningPrivate(this, progress);
50 |
51 | setupLayout(progress, this);
52 |
53 | setFixedSize(thickness, thickness);
54 |
55 | [progress release];
56 |
57 | [pool drain];
58 | }
59 |
60 | void QProgressIndicatorSpinning::animate(bool animate)
61 | {
62 | Q_ASSERT(pimpl);
63 | if (!pimpl)
64 | return;
65 |
66 | if (animate)
67 | [pimpl->nsProgressIndicator startAnimation:nil];
68 | else
69 | [pimpl->nsProgressIndicator stopAnimation:nil];
70 | }
71 |
--------------------------------------------------------------------------------
/qprogressindicatorspinning_nonmac.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2011 by Mike McQuaid
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | #include "qprogressindicatorspinning.h"
24 |
25 | #include
26 | #include
27 | #include
28 |
29 | class QProgressIndicatorSpinningPrivate : public QObject
30 | {
31 | public:
32 | QProgressIndicatorSpinningPrivate(QProgressIndicatorSpinning *qProgressIndicatorSpinning,
33 | QMovie *movie)
34 | : QObject(qProgressIndicatorSpinning), movie(movie) {}
35 |
36 | QPointer movie;
37 | };
38 |
39 | QProgressIndicatorSpinning::QProgressIndicatorSpinning(QWidget *parent,
40 | Thickness thickness)
41 | : QWidget(parent)
42 | {
43 | QVBoxLayout *layout = new QVBoxLayout(this);
44 | layout->setMargin(0);
45 |
46 | QSize size(thickness, thickness);
47 | QMovie *movie = new QMovie(this);
48 | movie->setFileName(":/Qocoa/qprogressindicatorspinning_nonmac.gif");
49 | movie->setScaledSize(size);
50 | // Roughly match OSX speed.
51 | movie->setSpeed(200);
52 | pimpl = new QProgressIndicatorSpinningPrivate(this, movie);
53 |
54 | QLabel *label = new QLabel(this);
55 | label->setMovie(movie);
56 |
57 | layout->addWidget(label);
58 | setFixedSize(size);
59 | }
60 |
61 |
62 | void QProgressIndicatorSpinning::animate(bool animate)
63 | {
64 | Q_ASSERT(pimpl && pimpl->movie);
65 | if (!(pimpl && pimpl->movie))
66 | return;
67 |
68 | if (animate)
69 | pimpl->movie->start();
70 | else
71 | pimpl->movie->stop();
72 | }
73 |
--------------------------------------------------------------------------------
/qprogressindicatorspinning_nonmac.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MikeMcQuaid/Qocoa/3a5623cb916e540ee46f5c13a85236ff458f4aba/qprogressindicatorspinning_nonmac.gif
--------------------------------------------------------------------------------
/qprogressindicatorspinning_nonmac.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | qprogressindicatorspinning_nonmac.gif
4 |
5 |
6 |
--------------------------------------------------------------------------------
/qsearchfield.h:
--------------------------------------------------------------------------------
1 | #ifndef QSEARCHFIELD_H
2 | #define QSEARCHFIELD_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | class QSearchFieldPrivate;
9 | class QSearchField : public QWidget
10 | {
11 | Q_OBJECT
12 |
13 | Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged USER true);
14 | Q_PROPERTY(QString placeholderText READ placeholderText WRITE setPlaceholderText);
15 |
16 | public:
17 | explicit QSearchField(QWidget *parent);
18 |
19 | QString text() const;
20 | QString placeholderText() const;
21 | void setFocus(Qt::FocusReason);
22 | void setMenu(QMenu *menu);
23 |
24 | public slots:
25 | void setText(const QString &text);
26 | void setPlaceholderText(const QString &text);
27 | void clear();
28 | void selectAll();
29 | void setFocus();
30 |
31 | signals:
32 | void textChanged(const QString &text);
33 | void editingFinished();
34 | void returnPressed();
35 |
36 | private slots:
37 | void popupMenu();
38 |
39 | protected:
40 | void changeEvent(QEvent*);
41 | void resizeEvent(QResizeEvent*);
42 |
43 | private:
44 | friend class QSearchFieldPrivate;
45 | QPointer pimpl;
46 | };
47 |
48 | #endif // QSEARCHFIELD_H
49 |
--------------------------------------------------------------------------------
/qsearchfield_mac.mm:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2011 by Mike McQuaid
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | #include "qsearchfield.h"
24 |
25 | #include "qocoa_mac.h"
26 |
27 | #import "Foundation/NSAutoreleasePool.h"
28 | #import "Foundation/NSNotification.h"
29 | #import "AppKit/NSSearchField.h"
30 |
31 | #include
32 | #include
33 | #include
34 |
35 | class QSearchFieldPrivate : public QObject
36 | {
37 | public:
38 | QSearchFieldPrivate(QSearchField *qSearchField, NSSearchField *nsSearchField)
39 | : QObject(qSearchField), qSearchField(qSearchField), nsSearchField(nsSearchField) {}
40 |
41 | void textDidChange(const QString &text)
42 | {
43 | if (qSearchField)
44 | emit qSearchField->textChanged(text);
45 | }
46 |
47 | void textDidEndEditing()
48 | {
49 | if (qSearchField)
50 | emit qSearchField->editingFinished();
51 | }
52 |
53 | void returnPressed()
54 | {
55 | if (qSearchField) {
56 | emit qSearchField->returnPressed();
57 | QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier);
58 | QApplication::postEvent(qSearchField, event);
59 | }
60 | }
61 |
62 | void keyDownPressed()
63 | {
64 | if (qSearchField) {
65 | QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);
66 | QApplication::postEvent(qSearchField, event);
67 | }
68 | }
69 |
70 | void keyUpPressed()
71 | {
72 | if (qSearchField) {
73 | QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);
74 | QApplication::postEvent(qSearchField, event);
75 | }
76 | }
77 |
78 | QPointer qSearchField;
79 | NSSearchField *nsSearchField;
80 | };
81 |
82 | @interface QSearchFieldDelegate : NSObject
83 | {
84 | @public
85 | QPointer pimpl;
86 | }
87 | -(void)controlTextDidChange:(NSNotification*)notification;
88 | -(void)controlTextDidEndEditing:(NSNotification*)notification;
89 | @end
90 |
91 | @implementation QSearchFieldDelegate
92 | -(void)controlTextDidChange:(NSNotification*)notification {
93 | Q_ASSERT(pimpl);
94 | if (pimpl)
95 | pimpl->textDidChange(toQString([[notification object] stringValue]));
96 | }
97 |
98 | -(void)controlTextDidEndEditing:(NSNotification*)notification {
99 | Q_UNUSED(notification);
100 | // No Q_ASSERT here as it is called on destruction.
101 | if (pimpl)
102 | pimpl->textDidEndEditing();
103 |
104 | if ([[[notification userInfo] objectForKey:@"NSTextMovement"] intValue] == NSReturnTextMovement)
105 | pimpl->returnPressed();
106 | }
107 |
108 | -(BOOL)control: (NSControl *)control textView:
109 | (NSTextView *)textView doCommandBySelector:
110 | (SEL)commandSelector {
111 | Q_ASSERT(pimpl);
112 | if (!pimpl) return NO;
113 |
114 | if (commandSelector == @selector(moveDown:)) {
115 | pimpl->keyDownPressed();
116 | return YES;
117 | } else if (commandSelector == @selector(moveUp:)) {
118 | pimpl->keyUpPressed();
119 | return YES;
120 | }
121 | return NO;
122 | }
123 |
124 | @end
125 |
126 | @interface QocoaSearchField : NSSearchField
127 | -(BOOL)performKeyEquivalent:(NSEvent*)event;
128 | @end
129 |
130 | @implementation QocoaSearchField
131 | -(BOOL)performKeyEquivalent:(NSEvent*)event {
132 | // First, check if we have the focus.
133 | // If no, it probably means this event isn't for us.
134 | NSResponder* firstResponder = [[NSApp keyWindow] firstResponder];
135 | if ([firstResponder isKindOfClass:[NSText class]] &&
136 | [(NSText*)firstResponder delegate] == self) {
137 |
138 | if ([event type] == NSKeyDown && [event modifierFlags] & NSCommandKeyMask)
139 | {
140 | QString keyString = toQString([event characters]);
141 | if (keyString == "a") // Cmd+a
142 | {
143 | [self performSelector:@selector(selectText:)];
144 | return YES;
145 | }
146 | else if (keyString == "c") // Cmd+c
147 | {
148 | [[self currentEditor] copy: nil];
149 | return YES;
150 | }
151 | else if (keyString == "v") // Cmd+v
152 | {
153 | [[self currentEditor] paste: nil];
154 | return YES;
155 | }
156 | else if (keyString == "x") // Cmd+x
157 | {
158 | [[self currentEditor] cut: nil];
159 | return YES;
160 | }
161 | }
162 | }
163 |
164 | return NO;
165 | }
166 | @end
167 |
168 | QSearchField::QSearchField(QWidget *parent) : QWidget(parent)
169 | {
170 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
171 |
172 | NSSearchField *search = [[QocoaSearchField alloc] init];
173 |
174 | QSearchFieldDelegate *delegate = [[QSearchFieldDelegate alloc] init];
175 | pimpl = delegate->pimpl = new QSearchFieldPrivate(this, search);
176 | [search setDelegate:delegate];
177 |
178 | setupLayout(search, this);
179 |
180 | setFixedHeight(24);
181 | setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
182 |
183 | [search release];
184 |
185 | [pool drain];
186 | }
187 |
188 | void QSearchField::setMenu(QMenu *menu)
189 | {
190 | Q_ASSERT(pimpl);
191 | if (!pimpl)
192 | return;
193 |
194 | #if QT_VERSION < QT_VERSION_CHECK(5,0,0)
195 | NSMenu *nsMenu = menu->macMenu();
196 | #else
197 | NSMenu *nsMenu = menu->toNSMenu();
198 | #endif
199 |
200 | [[pimpl->nsSearchField cell] setSearchMenuTemplate:nsMenu];
201 | }
202 |
203 | void QSearchField::popupMenu()
204 | {
205 | }
206 |
207 | void QSearchField::setText(const QString &text)
208 | {
209 | Q_ASSERT(pimpl);
210 | if (!pimpl)
211 | return;
212 |
213 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
214 | [pimpl->nsSearchField setStringValue:fromQString(text)];
215 | [pool drain];
216 | }
217 |
218 | void QSearchField::setPlaceholderText(const QString &text)
219 | {
220 | Q_ASSERT(pimpl);
221 | if (!pimpl)
222 | return;
223 |
224 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
225 | [[pimpl->nsSearchField cell] setPlaceholderString:fromQString(text)];
226 | [pool drain];
227 | }
228 |
229 | void QSearchField::clear()
230 | {
231 | Q_ASSERT(pimpl);
232 | if (!pimpl)
233 | return;
234 |
235 | [pimpl->nsSearchField setStringValue:@""];
236 | emit textChanged(QString());
237 | }
238 |
239 | void QSearchField::selectAll()
240 | {
241 | Q_ASSERT(pimpl);
242 | if (!pimpl)
243 | return;
244 |
245 | [pimpl->nsSearchField performSelector:@selector(selectText:)];
246 | }
247 |
248 | QString QSearchField::text() const
249 | {
250 | Q_ASSERT(pimpl);
251 | if (!pimpl)
252 | return QString();
253 |
254 | return toQString([pimpl->nsSearchField stringValue]);
255 | }
256 |
257 | QString QSearchField::placeholderText() const
258 | {
259 | Q_ASSERT(pimpl);
260 | if (!pimpl)
261 | return QString();
262 |
263 | return toQString([[pimpl->nsSearchField cell] placeholderString]);
264 | }
265 |
266 | void QSearchField::setFocus(Qt::FocusReason)
267 | {
268 | Q_ASSERT(pimpl);
269 | if (!pimpl)
270 | return;
271 |
272 | if ([pimpl->nsSearchField acceptsFirstResponder])
273 | [[pimpl->nsSearchField window] makeFirstResponder: pimpl->nsSearchField];
274 | }
275 |
276 | void QSearchField::setFocus()
277 | {
278 | setFocus(Qt::OtherFocusReason);
279 | }
280 |
281 | void QSearchField::changeEvent(QEvent* event)
282 | {
283 | if (event->type() == QEvent::EnabledChange) {
284 | Q_ASSERT(pimpl);
285 | if (!pimpl)
286 | return;
287 |
288 | const bool enabled = isEnabled();
289 | [pimpl->nsSearchField setEnabled: enabled];
290 | }
291 | QWidget::changeEvent(event);
292 | }
293 |
294 | void QSearchField::resizeEvent(QResizeEvent *resizeEvent)
295 | {
296 | QWidget::resizeEvent(resizeEvent);
297 | }
298 |
--------------------------------------------------------------------------------
/qsearchfield_nonmac.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2011 by Mike McQuaid
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | #include "qsearchfield.h"
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | #include
33 | #include
34 |
35 | class QSearchFieldPrivate : public QObject
36 | {
37 | public:
38 | QSearchFieldPrivate(QSearchField *searchField, QLineEdit *lineEdit, QToolButton *clearButton, QToolButton *searchButton)
39 | : QObject(searchField), lineEdit(lineEdit), clearButton(clearButton), searchButton(searchButton) {}
40 |
41 | int lineEditFrameWidth() const {
42 | return lineEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
43 | }
44 |
45 | int clearButtonPaddedWidth() const {
46 | return clearButton->width() + lineEditFrameWidth() * 2;
47 | }
48 |
49 | int clearButtonPaddedHeight() const {
50 | return clearButton->height() + lineEditFrameWidth() * 2;
51 | }
52 |
53 | int searchButtonPaddedWidth() const {
54 | return searchButton->width() + lineEditFrameWidth() * 2;
55 | }
56 |
57 | int searchButtonPaddedHeight() const {
58 | return searchButton->height() + lineEditFrameWidth() * 2;
59 | }
60 |
61 | QPointer lineEdit;
62 | QPointer clearButton;
63 | QPointer searchButton;
64 | QPointer searchMenu;
65 | };
66 |
67 | QSearchField::QSearchField(QWidget *parent) : QWidget(parent)
68 | {
69 | QLineEdit *lineEdit = new QLineEdit(this);
70 | connect(lineEdit, SIGNAL(textChanged(QString)),
71 | this, SIGNAL(textChanged(QString)));
72 | connect(lineEdit, SIGNAL(editingFinished()),
73 | this, SIGNAL(editingFinished()));
74 | connect(lineEdit, SIGNAL(returnPressed()),
75 | this, SIGNAL(returnPressed()));
76 | connect(lineEdit, SIGNAL(textChanged(QString)),
77 | this, SLOT(setText(QString)));
78 |
79 | int iconsize = style()->pixelMetric(QStyle::PM_SmallIconSize);
80 | QToolButton *clearButton = new QToolButton(this);
81 | QIcon clearIcon = QIcon::fromTheme(QLatin1String("edit-clear"),
82 | QIcon(QLatin1String(":/Qocoa/qsearchfield_nonmac_clear.png")));
83 | clearButton->setIcon(clearIcon);
84 | clearButton->setIconSize(QSize(iconsize, iconsize));
85 | clearButton->setFixedSize(QSize(iconsize, iconsize));
86 | clearButton->setStyleSheet("border: none;");
87 | clearButton->hide();
88 | connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));
89 |
90 | QToolButton *searchButton = new QToolButton(this);
91 | QIcon searchIcon = QIcon(QLatin1String(":/Qocoa/qsearchfield_nonmac_magnifier.png"));
92 | searchButton->setIcon(searchIcon);
93 | searchButton->setIconSize(QSize(iconsize, iconsize));
94 | searchButton->setFixedSize(QSize(iconsize, iconsize));
95 | searchButton->setStyleSheet("border: none;");
96 | searchButton->setPopupMode(QToolButton::InstantPopup);
97 | searchButton->setEnabled(false);
98 | connect(searchButton, SIGNAL(clicked()), this, SLOT(popupMenu()));
99 |
100 | pimpl = new QSearchFieldPrivate(this, lineEdit, clearButton, searchButton);
101 |
102 | lineEdit->setStyleSheet(QString("QLineEdit { padding-left: %1px; padding-right: %2px; } ")
103 | .arg(pimpl->searchButtonPaddedWidth())
104 | .arg(pimpl->clearButtonPaddedWidth()));
105 | const int width = qMax(lineEdit->minimumSizeHint().width(), pimpl->clearButtonPaddedWidth() + pimpl->searchButtonPaddedWidth());
106 | const int height = qMax(lineEdit->minimumSizeHint().height(),
107 | qMax(pimpl->clearButtonPaddedHeight(),
108 | pimpl->searchButtonPaddedHeight()));
109 | lineEdit->setMinimumSize(width, height);
110 |
111 | QVBoxLayout *layout = new QVBoxLayout(this);
112 | layout->setMargin(0);
113 | layout->addWidget(lineEdit);
114 | }
115 |
116 | void QSearchField::setMenu(QMenu *menu)
117 | {
118 | Q_ASSERT(pimpl);
119 | if (!pimpl)
120 | return;
121 |
122 | pimpl->searchMenu = menu;
123 |
124 | QIcon searchIcon = menu ? QIcon(QLatin1String(":/Qocoa/qsearchfield_nonmac_magnifier_menu.png"))
125 | : QIcon(QLatin1String(":/Qocoa/qsearchfield_nonmac_magnifier.png"));
126 | pimpl->searchButton->setIcon(searchIcon);
127 | pimpl->searchButton->setEnabled(isEnabled() && menu);
128 | }
129 |
130 | void QSearchField::popupMenu()
131 | {
132 | Q_ASSERT(pimpl);
133 | if (!pimpl)
134 | return;
135 |
136 | if (pimpl->searchMenu) {
137 | const QRect screenRect = qApp->desktop()->availableGeometry(pimpl->searchButton);
138 | const QSize sizeHint = pimpl->searchMenu->sizeHint();
139 | const QRect rect = pimpl->searchButton->rect();
140 | const int x = pimpl->searchButton->isRightToLeft()
141 | ? rect.right() - sizeHint.width()
142 | : rect.left();
143 | const int y = pimpl->searchButton->mapToGlobal(QPoint(0, rect.bottom())).y() + sizeHint.height() <= screenRect.height()
144 | ? rect.bottom()
145 | : rect.top() - sizeHint.height();
146 | QPoint point = pimpl->searchButton->mapToGlobal(QPoint(x, y));
147 | point.rx() = qMax(screenRect.left(), qMin(point.x(), screenRect.right() - sizeHint.width()));
148 | point.ry() += 1;
149 |
150 | pimpl->searchMenu->popup(point);
151 | }
152 | }
153 |
154 | void QSearchField::changeEvent(QEvent* event)
155 | {
156 | if (event->type() == QEvent::EnabledChange) {
157 | Q_ASSERT(pimpl);
158 | if (!pimpl)
159 | return;
160 |
161 | const bool enabled = isEnabled();
162 | pimpl->searchButton->setEnabled(enabled && pimpl->searchMenu);
163 | pimpl->lineEdit->setEnabled(enabled);
164 | pimpl->clearButton->setEnabled(enabled);
165 | }
166 | QWidget::changeEvent(event);
167 | }
168 |
169 | void QSearchField::setText(const QString &text)
170 | {
171 | Q_ASSERT(pimpl && pimpl->clearButton && pimpl->lineEdit);
172 | if (!(pimpl && pimpl->clearButton && pimpl->lineEdit))
173 | return;
174 |
175 | pimpl->clearButton->setVisible(!text.isEmpty());
176 |
177 | if (text != this->text())
178 | pimpl->lineEdit->setText(text);
179 | }
180 |
181 | void QSearchField::setPlaceholderText(const QString &text)
182 | {
183 | Q_ASSERT(pimpl && pimpl->lineEdit);
184 | if (!(pimpl && pimpl->lineEdit))
185 | return;
186 |
187 | #if QT_VERSION >= 0x040700
188 | pimpl->lineEdit->setPlaceholderText(text);
189 | #endif
190 | }
191 |
192 | void QSearchField::clear()
193 | {
194 | Q_ASSERT(pimpl && pimpl->lineEdit);
195 | if (!(pimpl && pimpl->lineEdit))
196 | return;
197 |
198 | pimpl->lineEdit->clear();
199 | }
200 |
201 | void QSearchField::selectAll()
202 | {
203 | Q_ASSERT(pimpl && pimpl->lineEdit);
204 | if (!(pimpl && pimpl->lineEdit))
205 | return;
206 |
207 | pimpl->lineEdit->selectAll();
208 | }
209 |
210 | QString QSearchField::text() const
211 | {
212 | Q_ASSERT(pimpl && pimpl->lineEdit);
213 | if (!(pimpl && pimpl->lineEdit))
214 | return QString();
215 |
216 | return pimpl->lineEdit->text();
217 | }
218 |
219 | QString QSearchField::placeholderText() const {
220 | Q_ASSERT(pimpl && pimpl->lineEdit);
221 | if (!(pimpl && pimpl->lineEdit))
222 | return QString();
223 |
224 | #if QT_VERSION >= 0x040700
225 | return pimpl->lineEdit->placeholderText();
226 | #else
227 | return QString();
228 | #endif
229 | }
230 |
231 | void QSearchField::setFocus(Qt::FocusReason reason)
232 | {
233 | Q_ASSERT(pimpl && pimpl->lineEdit);
234 | if (pimpl && pimpl->lineEdit)
235 | pimpl->lineEdit->setFocus(reason);
236 | }
237 |
238 | void QSearchField::setFocus()
239 | {
240 | setFocus(Qt::OtherFocusReason);
241 | }
242 |
243 | void QSearchField::resizeEvent(QResizeEvent *resizeEvent)
244 | {
245 | Q_ASSERT(pimpl && pimpl->clearButton && pimpl->lineEdit);
246 | if (!(pimpl && pimpl->clearButton && pimpl->lineEdit))
247 | return;
248 |
249 | QWidget::resizeEvent(resizeEvent);
250 | const int x = width() - pimpl->clearButtonPaddedWidth();
251 | const int y = (height() - pimpl->clearButton->height())/2;
252 | pimpl->clearButton->move(x, y);
253 |
254 | pimpl->searchButton->move(pimpl->lineEditFrameWidth() * 2,
255 | (height() - pimpl->searchButton->height())/2);
256 | }
257 |
--------------------------------------------------------------------------------
/qsearchfield_nonmac.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | qsearchfield_nonmac_clear.png
4 | qsearchfield_nonmac_magnifier_menu.png
5 | qsearchfield_nonmac_magnifier.png
6 |
7 |
8 |
--------------------------------------------------------------------------------
/qsearchfield_nonmac_clear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MikeMcQuaid/Qocoa/3a5623cb916e540ee46f5c13a85236ff458f4aba/qsearchfield_nonmac_clear.png
--------------------------------------------------------------------------------
/qsearchfield_nonmac_magnifier.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MikeMcQuaid/Qocoa/3a5623cb916e540ee46f5c13a85236ff458f4aba/qsearchfield_nonmac_magnifier.png
--------------------------------------------------------------------------------
/qsearchfield_nonmac_magnifier_menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MikeMcQuaid/Qocoa/3a5623cb916e540ee46f5c13a85236ff458f4aba/qsearchfield_nonmac_magnifier_menu.png
--------------------------------------------------------------------------------