diff --git a/.gitignore b/.gitignore index e4bce1768..efb18c4b3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ Makefile .qmake.stash effects/frei0r - +ts/*.qm diff --git a/cursors/cursors.qrc b/cursors/cursors.qrc new file mode 100644 index 000000000..0d40e1940 --- /dev/null +++ b/cursors/cursors.qrc @@ -0,0 +1,6 @@ + + + left_side.png + right_side.png + + diff --git a/cursors/left_side.png b/cursors/left_side.png new file mode 100644 index 000000000..2c6cac0aa Binary files /dev/null and b/cursors/left_side.png differ diff --git a/cursors/right_side.png b/cursors/right_side.png new file mode 100644 index 000000000..53fab01c6 Binary files /dev/null and b/cursors/right_side.png differ diff --git a/debian/rules b/debian/rules index 9a794c695..6bb702cee 100755 --- a/debian/rules +++ b/debian/rules @@ -4,6 +4,10 @@ export QT_SELECT := qt5 %: dh $@ +override_dh_auto_configure: + ls -a + dh_auto_configure + override_dh_auto_build: lrelease olive.pro dh_auto_build diff --git a/dialogs/proxydialog.cpp b/dialogs/proxydialog.cpp index 5e646abd7..9aef33dcb 100644 --- a/dialogs/proxydialog.cpp +++ b/dialogs/proxydialog.cpp @@ -71,6 +71,9 @@ ProxyDialog::ProxyDialog(QWidget *parent, const QVector &footage) : void ProxyDialog::accept() { QVector info_list; + // set to TRUE if any existing proxies exist and the user chooses to overwrite all of them + bool overwrite_all_existing = false; + for (int i=0;iget_type() == MEDIA_TYPE_FOLDER) { + + // if this item is a folder, recursively run this function to search it too if (reveal_media(media, item)) return true; + } else if (m == media) { - // expand all folders leading to this media + // if m == media, then we found the media object we were looking for + + // get sorter proxy item (the item that's "visible") QModelIndex sorted_index = sorter->mapFromSource(item); + // retrieve its parent item QModelIndex hierarchy = sorted_index.parent(); if (config.project_view_type == PROJECT_VIEW_TREE) { + + // if we're in tree view, expand every folder in the hierarchy containing the media while (hierarchy.isValid()) { tree_view->setExpanded(hierarchy, true); hierarchy = hierarchy.parent(); } - // select item + // select item (requires a QItemSelection object to select the whole row) QItemSelection row_select( sorter->index(sorted_index.row(), 0, sorted_index.parent()), sorter->index(sorted_index.row(), sorter->columnCount()-1, sorted_index.parent()) @@ -838,9 +846,16 @@ bool Project::reveal_media(Media *media, QModelIndex parent) { tree_view->selectionModel()->select(row_select, QItemSelectionModel::Select); } else if (config.project_view_type == PROJECT_VIEW_ICON) { + + // if we're in icon view, we just "browse" to the parent folder icon_view->setRootIndex(hierarchy); + + // select item in this folder icon_view->selectionModel()->select(sorted_index, QItemSelectionModel::Select); + + // update the "up" button state set_up_dir_enabled(); + } return true; diff --git a/ts/olive_cs.ts b/ts/olive_cs.ts index eedba77d9..fb181d259 100644 --- a/ts/olive_cs.ts +++ b/ts/olive_cs.ts @@ -1,6 +1,6 @@ - + AboutDialog @@ -27,12 +27,12 @@ Advanced Video Settings - + Pokročilá nastavení obrazu Pixel Format: - + Formát pixelu: @@ -196,54 +196,54 @@ Load Settings From File - + Nahrát nastavení ze souboru Save Settings to File - + Uložit nastavení do souboru Save Effect Settings - + Uložit nastavení efektu Effect XML Settings %1 - + Nastavení XML efektu %1 Save Settings Failed - + Nastavení se nepodařilo uložit Failed to open "%1" for writing. - + Nepodařilo se otevřít "%1" pro zápis. Load Effect Settings - + Nahrát nastavení efektu Load Settings Failed - + Nastavení se nepodařilo nahrát Failed to open "%1" for reading. - + Nepodařilo se otevřít "%1" pro čtení. This settings file doesn't match this effect. - + Tento soubor s nastavením neodpovídá tomuto efektu. @@ -325,7 +325,7 @@ Unknown codec name %1 - + Neznámý název kodeku %1 @@ -386,17 +386,17 @@ Invalid Codec - + Neplatný kodek Failed to find a suitable encoder for this codec. Export will likely fail. - + Nepodařilo se najít vhodný kodér pro tento kodek. Vyvedení pravděpodobně selže. Failed to find pixel format for this encoder. Export will likely fail. - + Nepodařilo se najít formát pixelu pro tento kodér. Vyvedení pravděpodobně selže. @@ -482,7 +482,7 @@ Advanced - + Pokročilé @@ -844,7 +844,7 @@ Enable/Disable In/Out Point - Povolit/Zakázat bod začátku/konce + Povolit/Zakázat bod začátku/konce @@ -869,7 +869,7 @@ Please open the sequence you wish to export. - Otevřete, prosím, sekvence, již chcete vyvést. + Otevřete, prosím, sekvenci, již chcete vyvést. @@ -1214,29 +1214,29 @@ Shuttle Left - + Jezdit tam a zpět vlevo Shuttle Stop - + Zastavit pendlování Shuttle Right - + Jezdit tam a zpět vpravo Decrease Speed - Snížit rychlost + Snížit rychlost Pause - Pozastavit + Pozastavit Increase Speed - Zvýšit rychlost + Zvýšit rychlost @@ -1281,8 +1281,7 @@ Maximize Panel - Zvětšit panel - + Zvětšit panel @@ -1500,17 +1499,17 @@ Set Marker - Nastavit značku + Nastavit značku Set clip marker name: - + Nastavit název značky záběru: Set sequence marker name: - + Nastavit název značky sekvence: @@ -1542,12 +1541,12 @@ %1 fields (%2 frames) - %1 polí (%2 snímků) + %1 polí (%2 snímků) %1 field(s) (%2 frame(s)) - + %1 pole(í) (%2 snímek(y)) @@ -1612,20 +1611,20 @@ Rozložení zvuku: %6 Audio %1: %2Hz %3 channels - Zvuk %1: %2Hz %3 kanálů + Zvuk %1: %2Hz %3 kanálů Audio %1: %2Hz %3 - + Zvuk %1: %2Hz %3 %n channel(s) - - - - + + %n kanál + %n kanály + %n kanálů @@ -1795,7 +1794,7 @@ Rozložení zvuku: %6 Generating Proxy: %1% - + Vytvoření proxy: %1% @@ -1879,22 +1878,22 @@ Rozložení zvuku: %6 Delete All Previews - + Smazat všechny náhledy Are you sure you want to delete all previews? - + Opravdu chcete smazat všechny náhledy? Previews Deleted - + Náhledy smazány All previews deleted succesfully. You may have to re-open your current project for changes to take effect. - + Všechny náhledy byly úspěšně smazány. Možná budete muset nynější projekt otevřít znovu, aby se změny projevily. @@ -1949,7 +1948,7 @@ Rozložení zvuku: %6 Delete Previews - + Smazat náhledy @@ -1968,7 +1967,7 @@ Rozložení zvuku: %6 Disable Multithreading on Images - Zakázat vytvoření více vláken v jednom procesu na obrázky + Zakázat vytvoření více vláken v jednom procesu na obrázky @@ -2250,19 +2249,19 @@ Vyhledávat rychle (při hledání se mohou krátce ukázat nepřesné snímky - ProRes SQ - ProRes SQ + ProRes SQ ProRes LT - ProRes LT + ProRes LT DNxHD - DNxHD + DNxHD H.264 - H.264 + H.264 @@ -2277,12 +2276,12 @@ Vyhledávat rychle (při hledání se mohou krátce ukázat nepřesné snímky - Proxy file exists - + Soubor proxy existuje The file "%1" already exists. Do you wish to replace it? - + Soubor "%1" již existuje. Chcete jej nahradit? @@ -2295,7 +2294,7 @@ Vyhledávat rychle (při hledání se mohou krátce ukázat nepřesné snímky - Finished generating proxy for "%1" - + Dokončeno vytvoření proxy pro "%1" @@ -2515,12 +2514,12 @@ Vyhledávat rychle (při hledání se mohou krátce ukázat nepřesné snímky - Generating proxy: %1% complete - + Vytvoření proxy: %1% hotovo Create/Modify Proxy - + Vytvořit/Změnit proxy @@ -2530,12 +2529,12 @@ Vyhledávat rychle (při hledání se mohou krátce ukázat nepřesné snímky - Modify Proxy - + Změnit proxy Restore Original - + Obnovit původní @@ -2560,12 +2559,12 @@ Vyhledávat rychle (při hledání se mohou krátce ukázat nepřesné snímky - Delete proxy - + Smazat proxy Would you like to delete the proxy file "%1" as well? - + Chcete smazat i soubor proxy "%1"? @@ -2820,11 +2819,11 @@ Vyhledávat rychle (při hledání se mohou krátce ukázat nepřesné snímky - Set Marker - Nastavit značku + Nastavit značku Set marker name: - Nastavit název značky: + Nastavit název značky: @@ -2945,47 +2944,47 @@ Vyhledávat rychle (při hledání se mohou krátce ukázat nepřesné snímky - &Undo - &Zpět + &Zpět &Redo - + &Znovu C&ut - + Vyj&mout Cop&y - &Kopírovat + &Kopírovat &Paste - &Vložit + &Vložit R&ipple Delete - + &Vytáhnout (smazat a posunout) Sequence Settings - + Nastavení sekvence &Speed/Duration - + &Rychlost/Doba trvání Auto-s&cale - + Automatická &změna velikosti @@ -2995,17 +2994,17 @@ Vyhledávat rychle (při hledání se mohou krátce ukázat nepřesné snímky - &Nest - + &Vnořovat &Reveal in Project - + &Odkrýt v projektu R&ename - + &Přejmenovat @@ -3259,12 +3258,12 @@ Doba trvání: %4 Transition Length: - Délka: + Délka: Length - + Délka @@ -3299,7 +3298,7 @@ Doba trvání: %4 Failed to locate entry point for dynamic library. - + Nepodařilo se najít vstupní bod pro dynamickou knihovnu. diff --git a/ts/olive_ru.ts b/ts/olive_ru.ts index f09293692..bd00569fd 100644 --- a/ts/olive_ru.ts +++ b/ts/olive_ru.ts @@ -27,12 +27,12 @@ Advanced Video Settings - + Дополнительные параметры видео Pixel Format: - + Формат пикселей: @@ -385,12 +385,12 @@ Invalid Codec - + Некорректный кодек Failed to find a suitable encoder for this codec. Export will likely fail. - + Не удалось найти подходящий кодировщик для этого кодека. Экспорт не гарантирован. @@ -481,7 +481,7 @@ Advanced - + Дополнительно @@ -1213,17 +1213,17 @@ Shuttle Left - + Уменьшить скорость Shuttle Stop - + Пауза Shuttle Right - + Увеличить скорость Decrease Speed @@ -1340,27 +1340,27 @@ Selecting Also Seeks - + Выделение с перемоткой Edit Tool Also Seeks - + Выделение с перемоткой Edit Tool Selects Links - + Выделение выбирает связи Seek Also Selects - + Перемотка с выделением Seek to the End of Pastes - + Перемотка до конца вставок @@ -1370,7 +1370,7 @@ Enable Drag Files to Timeline - Разрешить перетаскивание файлов на таймлайн извне + Разрешить перетаскивание на таймлайн извне @@ -1460,17 +1460,17 @@ Missing recent project - + Отсутствует недавний проект The project '%1' no longer exists. Would you like to remove it from the recent projects list? - + Проект '%1' больше не существует. Удалить его из списка недавних? Invalid aspect ratio - + Некорректное соотношение сторон @@ -1480,7 +1480,7 @@ Enter custom aspect ratio - + Введите другое соотношение сторон @@ -1498,17 +1498,17 @@ Set Marker - Установить маркер + Установить маркер Set clip marker name: - Установить название маркера клипа: + Название маркера клипа: Set sequence marker name: - Установить название маркера последовательности: + Название маркера последовательности: @@ -1545,7 +1545,7 @@ %1 field(s) (%2 frame(s)) - + полей: %1 (кадров: %2) @@ -1620,10 +1620,10 @@ Audio Layout: %6 %n channel(s) - - - - + + %n канал + %n канала + %n каналов @@ -1639,7 +1639,7 @@ Audio Layout: %6 Auto (%1) - + Авто (%1) @@ -1877,22 +1877,22 @@ Audio Layout: %6 Delete All Previews - + Удалить все миниатюры Are you sure you want to delete all previews? - + Действительно удалить все миниатюры? Previews Deleted - + Миниатюры удалены All previews deleted succesfully. You may have to re-open your current project for changes to take effect. - + Все миниатюры успешно удалены. Возможно, понадобится заново открыть проект, чтобы изменения вступили в силу. @@ -1947,12 +1947,12 @@ Audio Layout: %6 Delete Previews - + Удалить миниатюры Use Software Fallbacks When Possible - + По возможности использовать программную реализацию вместо аппаратной @@ -2547,7 +2547,7 @@ Seek quickly (may briefly show inaccurate frames when seeking - doesn't aff Would you like to delete the proxy file "%1" as well? - + Заодно удалить прокси-файл "%1"? @@ -3250,7 +3250,7 @@ Duration: %4 Length - + Длительность diff --git a/ui/cursors.cpp b/ui/cursors.cpp new file mode 100644 index 000000000..5b6056748 --- /dev/null +++ b/ui/cursors.cpp @@ -0,0 +1,29 @@ +#include "cursors.h" + +#include +#include + +#include + +QCursor Olive::Cursor_LeftTrim; +QCursor Olive::Cursor_RightTrim; + +QCursor load_cursor(const QString& file, int hotX, int hotY, const bool& right_aligned){ + // load specified file into a pixmap + QPixmap temp(file); + + // set cursor's horizontal hotspot + if (right_aligned) { + hotX = temp.width() - hotX; + } + + // return cursor + return QCursor(temp, hotX, hotY); +} + +void init_custom_cursors(){ + qInfo() << "Initializing custom cursors"; + Olive::Cursor_LeftTrim = load_cursor(":/cursors/left_side.png", 0, -1, false); + Olive::Cursor_RightTrim = load_cursor(":/cursors/right_side.png", 0, -1, true); + qInfo() << "Finished initializing custom cursors"; +} diff --git a/ui/cursors.h b/ui/cursors.h new file mode 100644 index 000000000..f12f94868 --- /dev/null +++ b/ui/cursors.h @@ -0,0 +1,13 @@ +#ifndef CURSORS_H +#define CURSORS_H + +#include + +void init_custom_cursors(); + +namespace Olive{ + extern QCursor Cursor_LeftTrim; + extern QCursor Cursor_RightTrim; +} + +#endif // CURSORS_H diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 2f81dc070..82989339d 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -23,6 +23,7 @@ #include "mainwindow.h" #include "ui/rectangleselect.h" #include "playback/playback.h" +#include "ui/cursors.h" #include "debug.h" #include "project/effect.h" @@ -124,7 +125,9 @@ void TimelineWidget::show_context_menu(const QPoint& pos) { // set autoscale to the first selected clip autoscaleAction->setChecked(selected_clips.at(0)->autoscale); - menu.addAction(tr("Link/Unlink"), panel_timeline, SLOT(toggle_links())); + menu.addAction(tr("Enable/Disable"), mainWindow, SLOT(toggle_enable_clips())); + + menu.addAction(tr("Link/Unlink"), panel_timeline, SLOT(toggle_links())); menu.addAction(tr("&Nest"), mainWindow, SLOT(nest())); @@ -1977,62 +1980,132 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { } else if (panel_timeline->tool == TIMELINE_TOOL_POINTER || panel_timeline->tool == TIMELINE_TOOL_RIPPLE || panel_timeline->tool == TIMELINE_TOOL_ROLLING) { + + // hide any tooltip that may be currently showing QToolTip::hideText(); + // cache cursor position QPoint pos = event->pos(); + // + // check to see if the cursor is on a clip edge + // + + // threshold around a trim point that the cursor can be within and still considered "trimming" int lim = 5; + long mouse_frame_lower = panel_timeline->getTimelineFrameFromScreenPoint(pos.x()-lim)-1; + long mouse_frame_upper = panel_timeline->getTimelineFrameFromScreenPoint(pos.x()+lim)+1; + + // current track that the cursor is on int mouse_track = getTrackFromScreenPoint(pos.y()); - long mouse_frame_lower = panel_timeline->getTimelineFrameFromScreenPoint(pos.x()-lim)-1; - long mouse_frame_upper = panel_timeline->getTimelineFrameFromScreenPoint(pos.x()+lim)+1; - bool found = false; + + // used to determine whether we the cursor found a trim point or not + bool found = false; + + // used to determine whether the cursor is within the rect of a clip bool cursor_contains_clip = false; + + // used to determine how close the cursor is to a trim point + // (and more specifically, whether another point is closer or not) int closeness = INT_MAX; + + // while we loop through the clips, we cache the maximum/minimum tracks in this sequence int min_track = INT_MAX; int max_track = INT_MIN; + + // we default to selecting no transition, but set this accordingly if the cursor is on a transition panel_timeline->transition_select = TA_NO_TRANSITION; + + // set currently trimming clip to -1 (aka null) + panel_timeline->trim_target = -1; + + // loop through current clips in the sequence for (int i=0;iclips.size();i++) { Clip* c = sequence->clips.at(i); if (c != nullptr) { + + // cache track range min_track = qMin(min_track, c->track); max_track = qMax(max_track, c->track); + + // if this clip is on the same track the mouse is if (c->track == mouse_track) { + + // if this cursor is inside the boundaries of this clip (hovering over the clip) if (panel_timeline->cursor_frame >= c->timeline_in && panel_timeline->cursor_frame <= c->timeline_out) { + + // acknowledge that we are hovering over a clip cursor_contains_clip = true; + // start a timer to show a tooltip about this clip tooltip_timer.start(); tooltip_clip = i; - if (c->get_opening_transition() != nullptr && panel_timeline->cursor_frame <= c->timeline_in + c->get_opening_transition()->get_true_length()) { + // check if the cursor is specifically hovering over one of the clip's transitions + if (c->get_opening_transition() != nullptr + && panel_timeline->cursor_frame <= c->timeline_in + c->get_opening_transition()->get_true_length()) { + panel_timeline->transition_select = TA_OPENING_TRANSITION; - } else if (c->get_closing_transition() != nullptr && panel_timeline->cursor_frame >= c->timeline_out - c->get_closing_transition()->get_true_length()) { + + } else if (c->get_closing_transition() != nullptr + && panel_timeline->cursor_frame >= c->timeline_out - c->get_closing_transition()->get_true_length()) { + panel_timeline->transition_select = TA_CLOSING_TRANSITION; + } } + + // is the cursor hovering around the clip's IN point? if (c->timeline_in > mouse_frame_lower && c->timeline_in < mouse_frame_upper) { + + // test how close this IN point is to the cursor int nc = qAbs(c->timeline_in + 1 - panel_timeline->cursor_frame); + + // and test whether it's closer than the last in/out point we found if (nc < closeness) { + + // if so, this is the point we'll make active for now (unless we find a closer one later) panel_timeline->trim_target = i; panel_timeline->trim_in_point = true; closeness = nc; - found = true; + found = true; + } } + + // is the cursor hovering around the clip's OUT point? if (c->timeline_out > mouse_frame_lower && c->timeline_out < mouse_frame_upper) { + + // test how close this OUT point is to the cursor int nc = qAbs(c->timeline_out - 1 - panel_timeline->cursor_frame); + + // and test whether it's closer than the last in/out point we found if (nc < closeness) { + + // if so, this is the point we'll make active for now (unless we find a closer one later) panel_timeline->trim_target = i; panel_timeline->trim_in_point = false; closeness = nc; - found = true; + found = true; + } } + + // the pointer can be used to resize/trim transitions, here we test if the + // cursor is within the trim point of one of the clip's transitions if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { + + // if the clip has an opening transition if (c->get_opening_transition() != nullptr) { + + // cache the timeline frame where the transition ends long transition_point = c->timeline_in + c->get_opening_transition()->get_true_length(); + // check if the cursor is hovering around it (within the threshold) if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) { + + // similar to above, test how close it is and if it's closer, make this active int nc = qAbs(transition_point - 1 - panel_timeline->cursor_frame); if (nc < closeness) { panel_timeline->trim_target = i; @@ -2043,9 +2116,17 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { } } } + + // if the clip has a closing transition if (c->get_closing_transition() != nullptr) { + + // cache the timeline frame where the transition starts long transition_point = c->timeline_out - c->get_closing_transition()->get_true_length(); + + // check if the cursor is hovering around it (within the threshold) if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) { + + // similar to above, test how close it is and if it's closer, make this active int nc = qAbs(transition_point + 1 - panel_timeline->cursor_frame); if (nc < closeness) { panel_timeline->trim_target = i; @@ -2059,16 +2140,22 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { } } } - } - /*if (cursor_contains_clip) { - QToolTip::showText(mapToGlobal(event->pos()), "HOVER OVER CLIP"); - }*/ - if (found) { - setCursor(Qt::SizeHorCursor); - } else { - panel_timeline->trim_target = -1; + } - // look for track heights + // if the cursor is indeed on a clip edge, we set the cursor accordingly + if (found) { + + if (panel_timeline->trim_in_point) { // if we're trimming an IN point + setCursor(Olive::Cursor_LeftTrim); + } else { // if we're trimming an OUT point + setCursor(Olive::Cursor_RightTrim); + } + + } else { + // we didn't find a trim target, so we must be doing something else + // (e.g. dragging a clip or resizing the track heights) + + // check to see if we're resizing a track height int track_y = 0; for (int i=0;iget_track_height_size(bottom_align);i++) { int track = (bottom_align) ? -1-i : i;