1 /***
2 
3     Olive - Non-Linear Video Editor
4     Copyright (C) 2019  Olive Team
5 
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (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, see <http://www.gnu.org/licenses/>.
18 
19 ***/
20 
21 #include "menuhelper.h"
22 
23 #include <QMessageBox>
24 #include <QInputDialog>
25 #include <QPushButton>
26 #include <QStyleFactory>
27 
28 #include "global/config.h"
29 #include "project/clipboard.h"
30 #include "ui/mainwindow.h"
31 #include "global/global.h"
32 #include "panels/panels.h"
33 #include "ui/focusfilter.h"
34 
35 MenuHelper olive::MenuHelper;
36 
InitializeSharedMenus()37 void MenuHelper::InitializeSharedMenus()
38 {
39   new_project_ = create_menu_action(nullptr, "newproj", olive::Global.get(), SLOT(new_project()), QKeySequence("Ctrl+N"));
40   new_project_->setParent(this);
41 
42   new_sequence_ = create_menu_action(nullptr, "newseq", panel_project, SLOT(new_sequence()), QKeySequence("Ctrl+Shift+N"));
43   new_sequence_->setParent(this);
44 
45   new_folder_ = create_menu_action(nullptr, "newfolder", panel_project, SLOT(new_folder()));
46   new_folder_->setParent(this);
47 
48   set_in_point_ = create_menu_action(nullptr, "setinpoint", &olive::FocusFilter, SLOT(set_in_point()), QKeySequence("I"));
49   set_in_point_->setParent(this);
50 
51   set_out_point_ = create_menu_action(nullptr, "setoutpoint", &olive::FocusFilter, SLOT(set_out_point()), QKeySequence("O"));
52   set_out_point_->setParent(this);
53 
54   reset_in_point_ = create_menu_action(nullptr, "resetin", &olive::FocusFilter, SLOT(clear_in()));
55   reset_in_point_->setParent(this);
56 
57   reset_out_point_ = create_menu_action(nullptr, "resetout", &olive::FocusFilter, SLOT(clear_out()));
58   reset_out_point_->setParent(this);
59 
60   clear_inout_point = create_menu_action(nullptr, "clearinout", &olive::FocusFilter, SLOT(clear_inout()), QKeySequence("G"));
61   clear_inout_point->setParent(this);
62 
63   add_default_transition_ = create_menu_action(nullptr, "deftransition", panel_timeline, SLOT(add_transition()), QKeySequence("Ctrl+Shift+D"));
64   add_default_transition_->setParent(this);
65 
66   link_unlink_ = create_menu_action(nullptr, "linkunlink", panel_timeline, SLOT(toggle_links()), QKeySequence("Ctrl+L"));
67   link_unlink_->setParent(this);
68 
69   enable_disable_ = create_menu_action(nullptr, "enabledisable", panel_timeline, SLOT(toggle_enable_on_selected_clips()), QKeySequence("Shift+E"));
70   enable_disable_->setParent(this);
71 
72   nest_ = create_menu_action(nullptr, "nest", panel_timeline, SLOT(nest()));
73   nest_->setParent(this);
74 
75   cut_ = create_menu_action(nullptr, "cut", &olive::FocusFilter, SLOT(cut()), QKeySequence("Ctrl+X"));
76   cut_->setParent(this);
77 
78   copy_ = create_menu_action(nullptr, "copy", &olive::FocusFilter, SLOT(copy()), QKeySequence("Ctrl+C"));
79   copy_->setParent(this);
80 
81   paste_ = create_menu_action(nullptr, "paste", olive::Global.get(), SLOT(paste()), QKeySequence("Ctrl+V"));
82   paste_->setParent(this);
83 
84   paste_insert_ = create_menu_action(nullptr, "pasteinsert", olive::Global.get(), SLOT(paste_insert()), QKeySequence("Ctrl+Shift+V"));
85   paste_insert_->setParent(this);
86 
87   duplicate_ = create_menu_action(nullptr, "duplicate", &olive::FocusFilter, SLOT(duplicate()), QKeySequence("Ctrl+D"));
88   duplicate_->setParent(this);
89 
90   delete_ = create_menu_action(nullptr, "delete", &olive::FocusFilter, SLOT(delete_function()), QKeySequence("Del"));
91   delete_->setParent(this);
92 
93   ripple_delete_ = create_menu_action(nullptr, "rippledelete", panel_timeline, SLOT(ripple_delete()), QKeySequence("Shift+Del"));
94   ripple_delete_->setParent(this);
95 
96   split_ = create_menu_action(nullptr, "split", panel_timeline, SLOT(split_at_playhead()), QKeySequence("Ctrl+K"));
97   split_->setParent(this);
98 
99   Retranslate();
100 }
101 
make_new_menu(QMenu * parent)102 void MenuHelper::make_new_menu(QMenu *parent) {
103   parent->addAction(new_project_);
104   parent->addSeparator();
105   parent->addAction(new_sequence_);
106   parent->addAction(new_folder_);
107 }
108 
make_inout_menu(QMenu * parent)109 void MenuHelper::make_inout_menu(QMenu *parent) {
110   parent->addAction(set_in_point_);
111   parent->addAction(set_out_point_);
112   parent->addSeparator();
113   parent->addAction(reset_in_point_);
114   parent->addAction(reset_out_point_);
115   parent->addAction(clear_inout_point);
116 }
117 
make_clip_functions_menu(QMenu * parent)118 void MenuHelper::make_clip_functions_menu(QMenu *parent) {
119   parent->addAction(add_default_transition_);
120   parent->addAction(link_unlink_);
121   parent->addAction(enable_disable_);
122   parent->addAction(nest_);
123 }
124 
make_edit_functions_menu(QMenu * parent,bool objects_are_selected)125 void MenuHelper::make_edit_functions_menu(QMenu *parent, bool objects_are_selected) {
126   if (objects_are_selected) {
127     parent->addAction(cut_);
128     parent->addAction(copy_);
129   }
130 
131   parent->addAction(paste_);
132   parent->addAction(paste_insert_);
133 
134   if (objects_are_selected) {
135     parent->addAction(duplicate_);
136     parent->addAction(delete_);
137     parent->addAction(ripple_delete_);
138     parent->addAction(split_);
139   }
140 }
141 
set_bool_action_checked(QAction * a)142 void MenuHelper::set_bool_action_checked(QAction *a) {
143   if (!a->data().isNull()) {
144     bool* variable = reinterpret_cast<bool*>(a->data().value<quintptr>());
145     a->setChecked(*variable);
146   }
147 }
148 
set_int_action_checked(QAction * a,const int & i)149 void MenuHelper::set_int_action_checked(QAction *a, const int& i) {
150   if (!a->data().isNull()) {
151     a->setChecked(a->data() == i);
152   }
153 }
154 
set_button_action_checked(QAction * a)155 void MenuHelper::set_button_action_checked(QAction *a) {
156   a->setChecked(reinterpret_cast<QPushButton*>(a->data().value<quintptr>())->isChecked());
157 }
158 
Retranslate()159 void MenuHelper::Retranslate()
160 {
161   new_project_->setText(tr("&Project"));
162   new_sequence_->setText(tr("&Sequence"));
163   new_folder_->setText(tr("&Folder"));
164   set_in_point_->setText(tr("Set In Point"));
165   set_out_point_->setText(tr("Set Out Point"));
166   reset_in_point_->setText(tr("Reset In Point"));
167   reset_out_point_->setText(tr("Reset Out Point"));
168   clear_inout_point->setText(tr("Clear In/Out Point"));
169   add_default_transition_->setText(tr("Add Default Transition"));
170   link_unlink_->setText(tr("Link/Unlink"));
171   enable_disable_->setText(tr("Enable/Disable"));
172   nest_->setText(tr("Nest"));
173   cut_->setText(tr("Cu&t"));
174   copy_->setText(tr("Cop&y"));
175   paste_->setText(tr("&Paste"));
176   paste_insert_->setText(tr("Paste Insert"));
177   duplicate_->setText(tr("Duplicate"));
178   delete_->setText(tr("Delete"));
179   ripple_delete_->setText(tr("Ripple Delete"));
180   split_->setText(tr("Split"));
181 }
182 
toggle_bool_action()183 void MenuHelper::toggle_bool_action() {
184   QAction* action = static_cast<QAction*>(sender());
185   bool* variable = reinterpret_cast<bool*>(action->data().value<quintptr>());
186   *variable = !(*variable);
187   update_ui(false);
188 }
189 
set_titlesafe_from_menu()190 void MenuHelper::set_titlesafe_from_menu() {
191   double tsa = static_cast<QAction*>(sender())->data().toDouble();
192 
193   if (qIsNaN(tsa)) {
194 
195     // disable title safe area
196     olive::CurrentConfig.show_title_safe_area = false;
197 
198   } else {
199 
200     // using title safe area
201     olive::CurrentConfig.show_title_safe_area = true;
202 
203     // are we using the default area aspect ratio, or a specific one
204     if (qIsNull(tsa)) {
205 
206       // default title safe area
207       olive::CurrentConfig.use_custom_title_safe_ratio = false;
208 
209     } else {
210 
211       // using a specific aspect ratio
212       olive::CurrentConfig.use_custom_title_safe_ratio = true;
213 
214       if (tsa < 0.0) {
215 
216         // set a custom title safe area
217         QString input;
218         bool invalid = false;
219         QRegExp arTest("[0-9.]+:[0-9.]+");
220 
221         do {
222           if (invalid) {
223             QMessageBox::critical(olive::MainWindow, tr("Invalid aspect ratio"), tr("The aspect ratio '%1' is invalid. Please try again.").arg(input));
224           }
225 
226           input = QInputDialog::getText(olive::MainWindow, tr("Enter custom aspect ratio"), tr("Enter the aspect ratio to use for the title/action safe area (e.g. 16:9):"));
227           invalid = !arTest.exactMatch(input) && !input.isEmpty();
228         } while (invalid);
229 
230         if (!input.isEmpty()) {
231           QStringList inputList = input.split(':');
232           olive::CurrentConfig.custom_title_safe_ratio = inputList.at(0).toDouble()/inputList.at(1).toDouble();
233         }
234 
235       } else {
236 
237         // specified tsa is a specific custom aspect ratio
238         olive::CurrentConfig.custom_title_safe_ratio = tsa;
239       }
240 
241     }
242 
243   }
244 
245   panel_sequence_viewer->viewer_widget->update();
246 }
247 
set_autoscroll()248 void MenuHelper::set_autoscroll() {
249   QAction* action = static_cast<QAction*>(sender());
250   olive::CurrentConfig.autoscroll = action->data().toInt();
251 }
252 
menu_click_button()253 void MenuHelper::menu_click_button() {
254   reinterpret_cast<QPushButton*>(static_cast<QAction*>(sender())->data().value<quintptr>())->click();
255 }
256 
set_timecode_view()257 void MenuHelper::set_timecode_view() {
258   QAction* action = static_cast<QAction*>(sender());
259   olive::CurrentConfig.timecode_view = action->data().toInt();
260   update_ui(false);
261 }
262 
open_recent_from_menu()263 void MenuHelper::open_recent_from_menu() {
264   int index = static_cast<QAction*>(sender())->data().toInt();
265   olive::Global.get()->open_recent(index);
266 }
267 
create_effect_paste_action(QMenu * menu)268 void MenuHelper::create_effect_paste_action(QMenu *menu)
269 {
270   QAction* paste_action = menu->addAction(tr("&Paste"), panel_timeline, SLOT(paste(bool)));
271   paste_action->setEnabled(clipboard.size() > 0 && clipboard_type == CLIPBOARD_TYPE_EFFECT);
272 }
273 
create_submenu(QMenuBar * parent,const QObject * receiver,const char * member)274 Menu* MenuHelper::create_submenu(QMenuBar* parent,
275                                   const QObject *receiver,
276                                   const char *member) {
277   Menu* menu = new Menu(parent);
278 
279   /*
280   menu->setStyle(QStyleFactory::create("windowsvista"));
281   menu->setPalette(menu->style()->standardPalette());
282   menu->setStyleSheet("");
283   */
284 
285   parent->addMenu(menu);
286 
287   if (receiver != nullptr) {
288     QObject::connect(menu, SIGNAL(aboutToShow()), receiver, member);
289   }
290 
291   return menu;
292 }
293 
create_submenu(QMenu * parent)294 Menu* MenuHelper::create_submenu(QMenu* parent) {
295   Menu* menu = new Menu(parent);
296 
297   /*
298   menu->setStyle(QStyleFactory::create("windowsvista"));
299   menu->setPalette(menu->style()->standardPalette());
300   menu->setStyleSheet("");
301   */
302 
303   parent->addMenu(menu);
304   return menu;
305 }
306 
create_menu_action(QWidget * parent,const char * id,const QObject * receiver,const char * member,const QKeySequence & shortcut)307 QAction* MenuHelper::create_menu_action(QWidget *parent,
308                                         const char* id,
309                                         const QObject *receiver,
310                                         const char *member,
311                                         const QKeySequence &shortcut) {
312   QAction* action = new QAction(parent);
313   action->setProperty("id", id);
314   action->setShortcut(shortcut);
315 
316   if (receiver != nullptr) {
317     QObject::connect(action, SIGNAL(triggered(bool)), receiver, member);
318   }
319 
320   if (parent != nullptr) {
321     parent->addAction(action);
322   }
323 
324   return action;
325 }
326